From 205afe679855a4ce8149cdaa94d3f0868ce796dc Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Fri, 6 Feb 2015 21:38:51 +0000 Subject: Import LLDB as of upstream SVN r225923 (git 2b588ecd) This corresponds with the branchpoint for the 3.6 release. A number of files not required for the FreeBSD build have been removed. Sponsored by: DARPA, AFRL --- docs/lldb.1 | 32 +- include/lldb/API/LLDB.h | 1 + include/lldb/API/SBAddress.h | 1 + include/lldb/API/SBBreakpoint.h | 12 + include/lldb/API/SBCommandInterpreter.h | 70 +- include/lldb/API/SBCompileUnit.h | 3 + include/lldb/API/SBData.h | 1 + include/lldb/API/SBDebugger.h | 8 + include/lldb/API/SBDefines.h | 6 + include/lldb/API/SBEvent.h | 6 +- include/lldb/API/SBExecutionContext.h | 74 + include/lldb/API/SBFileSpec.h | 1 + include/lldb/API/SBFrame.h | 16 +- include/lldb/API/SBFunction.h | 3 + include/lldb/API/SBListener.h | 10 + include/lldb/API/SBProcess.h | 7 + include/lldb/API/SBSection.h | 12 + include/lldb/API/SBStream.h | 2 + include/lldb/API/SBTarget.h | 166 +- include/lldb/API/SBThread.h | 18 +- include/lldb/API/SBThreadCollection.h | 68 + include/lldb/API/SBThreadPlan.h | 129 + include/lldb/API/SBType.h | 72 + include/lldb/API/SBTypeSummary.h | 50 + include/lldb/API/SBValue.h | 11 + include/lldb/API/SBValueList.h | 3 + include/lldb/Breakpoint/Breakpoint.h | 81 +- include/lldb/Breakpoint/BreakpointID.h | 15 + include/lldb/Breakpoint/BreakpointIDList.h | 2 +- include/lldb/Breakpoint/BreakpointList.h | 14 + include/lldb/Breakpoint/BreakpointLocation.h | 23 +- .../lldb/Breakpoint/BreakpointLocationCollection.h | 9 + include/lldb/Breakpoint/BreakpointLocationList.h | 15 + include/lldb/Breakpoint/BreakpointResolver.h | 8 +- .../lldb/Breakpoint/BreakpointResolverAddress.h | 27 +- .../lldb/Breakpoint/BreakpointResolverFileLine.h | 19 +- .../lldb/Breakpoint/BreakpointResolverFileRegex.h | 19 +- include/lldb/Breakpoint/BreakpointResolverName.h | 23 +- include/lldb/Breakpoint/BreakpointSite.h | 6 + include/lldb/Core/Address.h | 1 + include/lldb/Core/ArchSpec.h | 29 +- include/lldb/Core/Communication.h | 6 +- include/lldb/Core/Connection.h | 2 + include/lldb/Core/ConnectionFileDescriptor.h | 118 - include/lldb/Core/DataBuffer.h | 2 + include/lldb/Core/DataExtractor.h | 27 +- include/lldb/Core/Debugger.h | 47 +- include/lldb/Core/Disassembler.h | 50 +- include/lldb/Core/FileSpecList.h | 5 +- include/lldb/Core/IOHandler.h | 315 ++- include/lldb/Core/Mangled.h | 3 +- include/lldb/Core/ModuleList.h | 17 + include/lldb/Core/PluginManager.h | 39 + include/lldb/Core/RegularExpression.h | 3 + include/lldb/Core/SearchFilter.h | 148 +- include/lldb/Core/Section.h | 14 +- include/lldb/Core/StreamString.h | 3 + include/lldb/Core/ThreadSafeDenseMap.h | 65 + include/lldb/Core/ThreadSafeSTLMap.h | 1 + include/lldb/Core/ValueObject.h | 88 +- include/lldb/Core/ValueObjectChild.h | 1 + include/lldb/Core/ValueObjectConstResult.h | 9 +- include/lldb/Core/ValueObjectConstResultImpl.h | 10 - include/lldb/Core/ValueObjectSyntheticFilter.h | 19 +- .../lldb/DataFormatters/CXXFormatterFunctions.h | 504 +--- include/lldb/DataFormatters/DataVisualization.h | 13 + include/lldb/DataFormatters/FormatCache.h | 20 +- include/lldb/DataFormatters/FormatManager.h | 23 + include/lldb/DataFormatters/FormattersContainer.h | 51 +- include/lldb/DataFormatters/StringPrinter.h | 290 +++ include/lldb/DataFormatters/TypeCategory.h | 51 +- include/lldb/DataFormatters/TypeCategoryMap.h | 10 + include/lldb/DataFormatters/TypeSummary.h | 43 +- include/lldb/DataFormatters/TypeSynthetic.h | 147 +- include/lldb/DataFormatters/TypeValidator.h | 280 ++ include/lldb/DataFormatters/ValueObjectPrinter.h | 143 +- include/lldb/Expression/ClangExpressionParser.h | 3 + include/lldb/Expression/ClangExpressionVariable.h | 5 + include/lldb/Expression/ClangFunction.h | 8 +- include/lldb/Expression/ClangModulesDeclVendor.h | 58 + include/lldb/Expression/ClangUserExpression.h | 2 - include/lldb/Expression/IRExecutionUnit.h | 159 +- include/lldb/Host/Config.h | 4 + include/lldb/Host/ConnectionFileDescriptor.h | 15 + include/lldb/Host/Editline.h | 482 ++-- include/lldb/Host/FileSpec.h | 16 +- include/lldb/Host/Host.h | 111 +- include/lldb/Host/HostInfoBase.h | 9 + include/lldb/Host/HostNativeProcess.h | 27 + include/lldb/Host/HostNativeProcessBase.h | 57 + include/lldb/Host/HostNativeThread.h | 25 + include/lldb/Host/HostNativeThreadBase.h | 53 + include/lldb/Host/HostNativeThreadForward.h | 30 + include/lldb/Host/HostProcess.h | 41 +- include/lldb/Host/HostThread.h | 56 + include/lldb/Host/MonitoringProcessLauncher.h | 30 + include/lldb/Host/Pipe.h | 86 +- include/lldb/Host/PipeBase.h | 54 + include/lldb/Host/Predicate.h | 1 + include/lldb/Host/ProcessLauncher.h | 28 + include/lldb/Host/Socket.h | 12 +- include/lldb/Host/ThisThread.h | 40 + include/lldb/Host/ThreadLauncher.h | 47 + include/lldb/Host/TimeValue.h | 10 + include/lldb/Host/freebsd/HostInfoFreeBSD.h | 1 + include/lldb/Host/freebsd/HostThreadFreeBSD.h | 31 + .../Host/posix/ConnectionFileDescriptorPosix.h | 108 + include/lldb/Host/posix/HostInfoPosix.h | 3 + include/lldb/Host/posix/HostProcessPosix.h | 26 +- include/lldb/Host/posix/HostThreadPosix.h | 34 + include/lldb/Host/posix/PipePosix.h | 81 + include/lldb/Host/posix/ProcessLauncherPosix.h | 25 + include/lldb/Interpreter/Args.h | 4 +- include/lldb/Interpreter/CommandInterpreter.h | 243 +- include/lldb/Interpreter/CommandObject.h | 7 +- .../lldb/Interpreter/CommandObjectRegexCommand.h | 15 +- .../Interpreter/OptionGroupValueObjectDisplay.h | 19 +- include/lldb/Interpreter/OptionValue.h | 47 +- include/lldb/Interpreter/OptionValueChar.h | 113 + include/lldb/Interpreter/OptionValueProperties.h | 14 +- include/lldb/Interpreter/OptionValues.h | 1 + include/lldb/Interpreter/Property.h | 5 +- include/lldb/Interpreter/ScriptInterpreter.h | 76 +- include/lldb/Interpreter/ScriptInterpreterPython.h | 35 +- include/lldb/Symbol/ClangASTContext.h | 44 +- include/lldb/Symbol/ClangASTType.h | 39 +- include/lldb/Symbol/ClangExternalASTSourceCommon.h | 16 +- include/lldb/Symbol/CompactUnwindInfo.h | 155 ++ include/lldb/Symbol/DWARFCallFrameInfo.h | 8 +- include/lldb/Symbol/DeclVendor.h | 73 + include/lldb/Symbol/FuncUnwinders.h | 77 +- include/lldb/Symbol/SymbolContext.h | 3 +- include/lldb/Symbol/Type.h | 77 + include/lldb/Symbol/TypeVendor.h | 61 - include/lldb/Symbol/UnwindPlan.h | 108 +- include/lldb/Symbol/UnwindTable.h | 4 + include/lldb/Target/ABI.h | 15 - include/lldb/Target/CPPLanguageRuntime.h | 15 +- include/lldb/Target/FileAction.h | 3 + include/lldb/Target/InstrumentationRuntime.h | 47 + .../lldb/Target/InstrumentationRuntimeStopInfo.h | 52 + include/lldb/Target/MemoryHistory.h | 42 + include/lldb/Target/ObjCLanguageRuntime.h | 15 +- include/lldb/Target/Platform.h | 32 +- include/lldb/Target/Process.h | 163 +- include/lldb/Target/ProcessLaunchInfo.h | 43 +- include/lldb/Target/StackFrame.h | 1 + include/lldb/Target/StopInfo.h | 9 + include/lldb/Target/Target.h | 41 +- include/lldb/Target/TargetList.h | 28 +- include/lldb/Target/Thread.h | 27 +- include/lldb/Target/ThreadCollection.h | 70 + include/lldb/Target/ThreadList.h | 30 +- include/lldb/Target/ThreadPlan.h | 5 +- include/lldb/Target/ThreadPlanPython.h | 80 + include/lldb/Target/ThreadPlanStepOverBreakpoint.h | 6 + include/lldb/Target/ThreadPlanStepRange.h | 4 +- include/lldb/Target/Unwind.h | 2 +- include/lldb/Utility/CleanUp.h | 5 +- include/lldb/Utility/Iterable.h | 5 + include/lldb/Utility/ProcessStructReader.h | 100 + include/lldb/Utility/RegisterNumber.h | 69 + include/lldb/Utility/StringLexer.h | 17 +- include/lldb/lldb-defines.h | 1 - include/lldb/lldb-enumerations.h | 74 +- include/lldb/lldb-forward.h | 18 +- include/lldb/lldb-private-enumerations.h | 15 +- include/lldb/lldb-private-interfaces.h | 6 +- include/lldb/lldb-private-types.h | 20 +- include/lldb/lldb-private.h | 4 + include/lldb/lldb-types.h | 11 +- source/API/SBAddress.cpp | 42 +- source/API/SBBreakpoint.cpp | 78 + source/API/SBCommandInterpreter.cpp | 192 +- source/API/SBCommunication.cpp | 4 +- source/API/SBCompileUnit.cpp | 8 + source/API/SBDebugger.cpp | 71 +- source/API/SBEvent.cpp | 6 + source/API/SBExecutionContext.cpp | 129 + source/API/SBFunction.cpp | 10 + source/API/SBHostOS.cpp | 36 +- source/API/SBInstruction.cpp | 17 +- source/API/SBInstructionList.cpp | 16 +- source/API/SBListener.cpp | 6 + source/API/SBPlatform.cpp | 3 +- source/API/SBProcess.cpp | 44 +- source/API/SBSection.cpp | 8 + source/API/SBTarget.cpp | 306 ++- source/API/SBThread.cpp | 105 +- source/API/SBThreadCollection.cpp | 97 + source/API/SBThreadPlan.cpp | 285 ++ source/API/SBType.cpp | 173 +- source/API/SBTypeSummary.cpp | 97 + source/API/SBValue.cpp | 123 +- source/API/SBValueList.cpp | 24 + source/Breakpoint/Breakpoint.cpp | 398 ++- source/Breakpoint/BreakpointID.cpp | 17 + source/Breakpoint/BreakpointIDList.cpp | 44 +- source/Breakpoint/BreakpointLocation.cpp | 23 +- source/Breakpoint/BreakpointLocationCollection.cpp | 1 + source/Breakpoint/BreakpointLocationList.cpp | 27 + source/Breakpoint/BreakpointOptions.cpp | 3 +- source/Breakpoint/BreakpointResolverAddress.cpp | 8 + source/Breakpoint/BreakpointResolverFileLine.cpp | 11 + source/Breakpoint/BreakpointResolverFileRegex.cpp | 7 + source/Breakpoint/BreakpointResolverName.cpp | 18 + source/Breakpoint/BreakpointSite.cpp | 9 + source/Commands/CommandCompletions.cpp | 6 +- source/Commands/CommandObjectBreakpoint.cpp | 588 ++++- source/Commands/CommandObjectBreakpoint.h | 14 +- source/Commands/CommandObjectBreakpointCommand.cpp | 112 +- source/Commands/CommandObjectCommands.cpp | 238 +- source/Commands/CommandObjectExpression.cpp | 6 +- source/Commands/CommandObjectMemory.cpp | 113 +- source/Commands/CommandObjectPlatform.cpp | 5 +- source/Commands/CommandObjectProcess.cpp | 27 +- source/Commands/CommandObjectSource.cpp | 12 +- source/Commands/CommandObjectSyntax.cpp | 6 + source/Commands/CommandObjectTarget.cpp | 120 +- source/Commands/CommandObjectThread.cpp | 666 +++-- source/Commands/CommandObjectType.cpp | 125 +- source/Commands/CommandObjectWatchpointCommand.cpp | 15 +- source/Core/Address.cpp | 13 +- source/Core/AddressRange.cpp | 2 +- source/Core/AddressResolverFileLine.cpp | 2 +- source/Core/ArchSpec.cpp | 141 +- source/Core/Communication.cpp | 25 +- source/Core/Connection.cpp | 16 + source/Core/ConnectionFileDescriptor.cpp | 815 ------ source/Core/ConnectionSharedMemory.cpp | 2 + source/Core/ConstString.cpp | 25 +- source/Core/DataExtractor.cpp | 52 +- source/Core/Debugger.cpp | 509 ++-- source/Core/Disassembler.cpp | 55 +- source/Core/FastDemangle.cpp | 1496 ++++++----- source/Core/FileSpecList.cpp | 4 +- source/Core/IOHandler.cpp | 236 +- source/Core/Log.cpp | 8 +- source/Core/Mangled.cpp | 61 + source/Core/Module.cpp | 37 +- source/Core/ModuleList.cpp | 20 + source/Core/PluginManager.cpp | 223 ++ source/Core/RegularExpression.cpp | 20 +- source/Core/SearchFilter.cpp | 92 +- source/Core/Section.cpp | 14 +- source/Core/StreamString.cpp | 16 + source/Core/ValueObject.cpp | 520 ++-- source/Core/ValueObjectCast.cpp | 2 +- source/Core/ValueObjectChild.cpp | 2 +- source/Core/ValueObjectConstResult.cpp | 18 +- source/Core/ValueObjectConstResultImpl.cpp | 56 +- source/Core/ValueObjectDynamicValue.cpp | 13 +- source/Core/ValueObjectMemory.cpp | 2 +- source/Core/ValueObjectSyntheticFilter.cpp | 60 +- source/Core/ValueObjectVariable.cpp | 43 +- source/DataFormatters/CF.cpp | 8 +- source/DataFormatters/CXXFormatterFunctions.cpp | 580 ++--- source/DataFormatters/Cocoa.cpp | 28 +- source/DataFormatters/DataVisualization.cpp | 24 + source/DataFormatters/FormatCache.cpp | 76 +- source/DataFormatters/FormatManager.cpp | 205 +- source/DataFormatters/LibCxx.cpp | 113 +- source/DataFormatters/LibCxxInitializerList.cpp | 145 ++ source/DataFormatters/LibCxxList.cpp | 61 +- source/DataFormatters/LibCxxMap.cpp | 215 +- source/DataFormatters/LibCxxUnorderedMap.cpp | 35 + source/DataFormatters/LibCxxVector.cpp | 157 ++ source/DataFormatters/LibStdcpp.cpp | 2 +- source/DataFormatters/NSArray.cpp | 17 +- source/DataFormatters/NSDictionary.cpp | 197 +- source/DataFormatters/NSIndexPath.cpp | 309 +++ source/DataFormatters/NSSet.cpp | 178 +- source/DataFormatters/StringPrinter.cpp | 650 +++++ source/DataFormatters/TypeCategory.cpp | 97 +- source/DataFormatters/TypeCategoryMap.cpp | 68 + source/DataFormatters/TypeFormat.cpp | 12 +- source/DataFormatters/TypeSummary.cpp | 56 +- source/DataFormatters/TypeSynthetic.cpp | 138 + source/DataFormatters/TypeValidator.cpp | 75 + source/DataFormatters/ValueObjectPrinter.cpp | 108 +- source/Expression/ClangASTSource.cpp | 239 +- source/Expression/ClangExpressionDeclMap.cpp | 51 +- source/Expression/ClangExpressionParser.cpp | 83 +- source/Expression/ClangExpressionVariable.cpp | 11 + source/Expression/ClangFunction.cpp | 22 +- source/Expression/ClangModulesDeclVendor.cpp | 372 +++ source/Expression/ClangUserExpression.cpp | 25 +- source/Expression/DWARFExpression.cpp | 7 +- source/Expression/IRExecutionUnit.cpp | 128 +- source/Expression/IRForTarget.cpp | 54 +- source/Host/common/Editline.cpp | 1735 ++++++++----- source/Host/common/File.cpp | 2 +- source/Host/common/FileSpec.cpp | 189 +- source/Host/common/Host.cpp | 471 +--- source/Host/common/HostInfoBase.cpp | 36 +- source/Host/common/HostNativeThreadBase.cpp | 82 + source/Host/common/HostProcess.cpp | 65 + source/Host/common/HostThread.cpp | 78 + source/Host/common/MonitoringProcessLauncher.cpp | 102 + source/Host/common/NativeProcessProtocol.cpp | 23 +- source/Host/common/NativeProcessProtocol.h | 23 +- source/Host/common/NativeThreadProtocol.h | 2 +- source/Host/common/Pipe.cpp | 171 -- source/Host/common/PipeBase.cpp | 27 + source/Host/common/Socket.cpp | 78 +- source/Host/common/SocketAddress.cpp | 10 +- source/Host/common/SoftwareBreakpoint.cpp | 19 +- source/Host/common/ThisThread.cpp | 52 + source/Host/common/ThreadLauncher.cpp | 74 + source/Host/freebsd/Host.cpp | 114 +- source/Host/freebsd/HostInfoFreeBSD.cpp | 6 + source/Host/freebsd/HostThreadFreeBSD.cpp | 77 + source/Host/freebsd/ThisThread.cpp | 30 + .../Host/posix/ConnectionFileDescriptorPosix.cpp | 797 ++++++ source/Host/posix/HostInfoPosix.cpp | 14 + source/Host/posix/HostProcessPosix.cpp | 47 +- source/Host/posix/HostThreadPosix.cpp | 74 + source/Host/posix/PipePosix.cpp | 378 +++ source/Host/posix/ProcessLauncherPosix.cpp | 33 + source/Interpreter/Args.cpp | 33 +- source/Interpreter/CommandInterpreter.cpp | 337 ++- source/Interpreter/CommandObject.cpp | 53 +- source/Interpreter/CommandObjectRegexCommand.cpp | 6 +- source/Interpreter/OptionGroupPlatform.cpp | 2 +- .../Interpreter/OptionGroupValueObjectDisplay.cpp | 13 +- source/Interpreter/OptionValue.cpp | 39 + source/Interpreter/OptionValueArch.cpp | 4 + source/Interpreter/OptionValueArray.cpp | 2 + source/Interpreter/OptionValueBoolean.cpp | 2 + source/Interpreter/OptionValueChar.cpp | 80 + source/Interpreter/OptionValueDictionary.cpp | 6 +- source/Interpreter/OptionValueEnumeration.cpp | 2 + source/Interpreter/OptionValueFileSpec.cpp | 2 + source/Interpreter/OptionValueFileSpecLIst.cpp | 8 +- source/Interpreter/OptionValueFormat.cpp | 2 + source/Interpreter/OptionValuePathMappings.cpp | 8 +- source/Interpreter/OptionValueProperties.cpp | 10 + source/Interpreter/OptionValueRegex.cpp | 2 + source/Interpreter/OptionValueSInt64.cpp | 2 + source/Interpreter/OptionValueString.cpp | 37 +- source/Interpreter/OptionValueUInt64.cpp | 2 + source/Interpreter/OptionValueUUID.cpp | 4 + source/Interpreter/Property.cpp | 15 +- source/Interpreter/ScriptInterpreter.cpp | 12 +- source/Interpreter/ScriptInterpreterPython.cpp | 221 +- source/Interpreter/embedded_interpreter.py | 2 +- source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp | 30 + source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h | 14 +- .../Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp | 34 +- source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h | 16 +- source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h | 14 +- source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h | 14 +- source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp | 1120 ++++++++ source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h | 143 + source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp | 1124 ++++++++ source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h | 143 + source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp | 14 +- source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h | 14 +- .../Disassembler/llvm/DisassemblerLLVMC.cpp | 37 +- .../DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp | 28 +- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 189 +- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.h | 4 + .../Instruction/ARM/EmulateInstructionARM.cpp | 2 + .../AddressSanitizer/AddressSanitizerRuntime.cpp | 314 +++ .../AddressSanitizer/AddressSanitizerRuntime.h | 86 + source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp | 30 +- source/Plugins/JITLoader/GDB/JITLoaderGDB.h | 4 + .../MemoryHistory/asan/MemoryHistoryASan.cpp | 183 ++ .../Plugins/MemoryHistory/asan/MemoryHistoryASan.h | 62 + .../BSD-Archive/ObjectContainerBSDArchive.cpp | 2 +- source/Plugins/ObjectFile/ELF/ELFHeader.cpp | 9 + source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 135 +- source/Plugins/ObjectFile/ELF/ObjectFileELF.h | 3 + .../Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp | 77 +- source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h | 6 +- source/Plugins/Platform/POSIX/PlatformPOSIX.cpp | 130 +- source/Plugins/Platform/POSIX/PlatformPOSIX.h | 56 +- .../gdb-server/PlatformRemoteGDBServer.cpp | 26 +- .../Platform/gdb-server/PlatformRemoteGDBServer.h | 7 +- source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp | 3 +- source/Plugins/Process/FreeBSD/ProcessMonitor.cpp | 66 +- source/Plugins/Process/FreeBSD/ProcessMonitor.h | 7 +- source/Plugins/Process/POSIX/POSIXThread.cpp | 45 +- source/Plugins/Process/POSIX/POSIXThread.h | 2 +- source/Plugins/Process/POSIX/ProcessPOSIX.cpp | 39 +- source/Plugins/Process/POSIX/ProcessPOSIX.h | 59 +- .../RegisterContextPOSIXProcessMonitor_arm64.cpp | 4 +- .../RegisterContextPOSIXProcessMonitor_mips64.cpp | 4 +- .../RegisterContextPOSIXProcessMonitor_powerpc.cpp | 321 +++ .../RegisterContextPOSIXProcessMonitor_powerpc.h | 95 + .../RegisterContextPOSIXProcessMonitor_x86.cpp | 9 +- source/Plugins/Process/Utility/ARMDefines.h | 34 +- .../Process/Utility/DynamicRegisterInfo.cpp | 12 + source/Plugins/Process/Utility/HistoryThread.cpp | 2 +- source/Plugins/Process/Utility/HistoryThread.h | 12 + source/Plugins/Process/Utility/HistoryUnwind.cpp | 2 - source/Plugins/Process/Utility/HistoryUnwind.h | 3 +- .../Plugins/Process/Utility/InferiorCallPOSIX.cpp | 24 +- source/Plugins/Process/Utility/InstructionUtils.h | 2 +- source/Plugins/Process/Utility/LinuxSignals.cpp | 2 +- .../Utility/RegisterContextFreeBSD_powerpc.cpp | 230 ++ .../Utility/RegisterContextFreeBSD_powerpc.h | 66 + .../Process/Utility/RegisterContextLLDB.cpp | 703 +++-- .../Plugins/Process/Utility/RegisterContextLLDB.h | 26 + .../RegisterContextMacOSXFrameBackchain.cpp | 3 +- .../Utility/RegisterContextPOSIX_powerpc.cpp | 273 ++ .../Process/Utility/RegisterContextPOSIX_powerpc.h | 173 ++ .../Process/Utility/RegisterContextPOSIX_x86.cpp | 578 ++--- .../Process/Utility/RegisterContextPOSIX_x86.h | 277 +- .../Utility/RegisterContextThreadMemory.cpp | 2 +- .../Process/Utility/RegisterContext_powerpc.h | 163 ++ .../Plugins/Process/Utility/RegisterInfos_arm64.h | 4 +- .../Plugins/Process/Utility/RegisterInfos_i386.h | 18 +- .../Process/Utility/RegisterInfos_powerpc.h | 144 ++ .../Plugins/Process/Utility/RegisterInfos_x86_64.h | 34 +- .../Process/Utility/StopInfoMachException.cpp | 8 +- source/Plugins/Process/Utility/UnwindLLDB.cpp | 46 +- source/Plugins/Process/Utility/UnwindLLDB.h | 3 +- .../Process/Utility/lldb-x86-register-enums.h | 461 ++-- source/Plugins/Process/elf-core/ProcessElfCore.cpp | 25 +- source/Plugins/Process/elf-core/ProcessElfCore.h | 24 +- .../elf-core/RegisterContextPOSIXCore_mips64.cpp | 2 +- .../elf-core/RegisterContextPOSIXCore_powerpc.cpp | 109 + .../elf-core/RegisterContextPOSIXCore_powerpc.h | 62 + .../elf-core/RegisterContextPOSIXCore_x86_64.cpp | 2 +- source/Plugins/Process/elf-core/ThreadElfCore.cpp | 20 +- .../Process/gdb-remote/GDBRemoteCommunication.cpp | 118 +- .../Process/gdb-remote/GDBRemoteCommunication.h | 4 +- .../gdb-remote/GDBRemoteCommunicationClient.cpp | 61 +- .../gdb-remote/GDBRemoteCommunicationServer.cpp | 236 +- .../gdb-remote/GDBRemoteCommunicationServer.h | 19 +- .../Process/gdb-remote/ProcessGDBRemote.cpp | 134 +- .../Plugins/Process/gdb-remote/ProcessGDBRemote.h | 97 +- .../DWARF/DWARFAbbreviationDeclaration.cpp | 16 +- .../Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp | 29 +- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h | 15 +- .../Plugins/SymbolFile/DWARF/DWARFDataExtractor.h | 3 + source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp | 24 +- .../SymbolFile/DWARF/DWARFDebugInfoEntry.cpp | 91 +- source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp | 20 +- source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h | 1 + .../SymbolFile/DWARF/DWARFDebugPubnames.cpp | 2 +- source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp | 153 +- source/Plugins/SymbolFile/DWARF/DWARFFormValue.h | 23 +- source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h | 6 +- .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 280 +- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h | 5 - .../InstEmulation/UnwindAssemblyInstEmulation.cpp | 3 +- .../UnwindAssembly/x86/UnwindAssembly-x86.cpp | 473 ++-- source/Symbol/ClangASTContext.cpp | 67 +- source/Symbol/ClangASTImporter.cpp | 2 +- source/Symbol/ClangASTType.cpp | 225 +- source/Symbol/ClangExternalASTSourceCommon.cpp | 38 +- source/Symbol/CompactUnwindInfo.cpp | 1215 +++++++++ source/Symbol/CompileUnit.cpp | 7 +- source/Symbol/DWARFCallFrameInfo.cpp | 41 +- source/Symbol/Declaration.cpp | 2 +- source/Symbol/FuncUnwinders.cpp | 379 +-- source/Symbol/LineTable.cpp | 1 - source/Symbol/ObjectFile.cpp | 6 +- source/Symbol/Symbol.cpp | 2 +- source/Symbol/SymbolContext.cpp | 12 +- source/Symbol/Type.cpp | 112 + source/Symbol/UnwindPlan.cpp | 77 +- source/Symbol/UnwindTable.cpp | 16 +- source/Symbol/Variable.cpp | 4 +- source/Target/CPPLanguageRuntime.cpp | 78 +- source/Target/FileAction.cpp | 32 +- source/Target/InstrumentationRuntime.cpp | 48 + source/Target/InstrumentationRuntimeStopInfo.cpp | 36 + source/Target/LanguageRuntime.cpp | 56 +- source/Target/Memory.cpp | 19 +- source/Target/MemoryHistory.cpp | 30 + source/Target/ObjCLanguageRuntime.cpp | 8 +- source/Target/Platform.cpp | 281 +- source/Target/Process.cpp | 518 +++- source/Target/ProcessLaunchInfo.cpp | 180 +- source/Target/StackFrame.cpp | 55 +- source/Target/StackFrameList.cpp | 15 +- source/Target/StopInfo.cpp | 24 +- source/Target/Target.cpp | 218 +- source/Target/TargetList.cpp | 134 +- source/Target/Thread.cpp | 259 +- source/Target/ThreadCollection.cpp | 62 + source/Target/ThreadList.cpp | 23 +- source/Target/ThreadPlanPython.cpp | 192 ++ source/Target/ThreadPlanStepInRange.cpp | 30 +- source/Target/ThreadPlanStepInstruction.cpp | 29 +- source/Target/ThreadPlanStepOut.cpp | 51 +- source/Target/ThreadPlanStepOverBreakpoint.cpp | 35 +- source/Target/ThreadPlanStepOverRange.cpp | 26 +- source/Target/ThreadPlanStepRange.cpp | 8 +- source/Target/ThreadPlanStepThrough.cpp | 5 +- source/Target/ThreadPlanTracer.cpp | 6 +- source/Utility/PseudoTerminal.cpp | 6 + source/Utility/RegisterNumber.cpp | 157 ++ source/Utility/StringExtractor.cpp | 105 +- source/Utility/StringExtractor.h | 7 + source/Utility/StringExtractorGDBRemote.cpp | 13 +- source/Utility/StringLexer.cpp | 78 +- source/Utility/UriParser.cpp | 58 + source/Utility/UriParser.h | 31 + source/lldb-log.cpp | 3 +- source/lldb.cpp | 39 + tools/compact-unwind/compact-unwind-dumper.c | 1215 +++++++++ tools/driver/Driver.cpp | 309 ++- tools/driver/Driver.h | 30 +- tools/driver/Platform.h | 14 +- tools/lldb-mi/Driver.cpp | 1067 ++++---- tools/lldb-mi/Driver.h | 153 +- tools/lldb-mi/MICmdArgContext.cpp | 388 +-- tools/lldb-mi/MICmdArgContext.h | 72 +- tools/lldb-mi/MICmdArgSet.cpp | 672 ++--- tools/lldb-mi/MICmdArgSet.h | 147 +- tools/lldb-mi/MICmdArgValBase.cpp | 211 +- tools/lldb-mi/MICmdArgValBase.h | 202 +- tools/lldb-mi/MICmdArgValConsume.cpp | 150 +- tools/lldb-mi/MICmdArgValConsume.h | 70 +- tools/lldb-mi/MICmdArgValFile.cpp | 306 +-- tools/lldb-mi/MICmdArgValFile.h | 64 +- tools/lldb-mi/MICmdArgValListBase.cpp | 318 +-- tools/lldb-mi/MICmdArgValListBase.h | 137 +- tools/lldb-mi/MICmdArgValListOfN.cpp | 259 +- tools/lldb-mi/MICmdArgValListOfN.h | 119 +- tools/lldb-mi/MICmdArgValNumber.cpp | 231 +- tools/lldb-mi/MICmdArgValNumber.h | 72 +- tools/lldb-mi/MICmdArgValOptionLong.cpp | 498 ++-- tools/lldb-mi/MICmdArgValOptionLong.h | 141 +- tools/lldb-mi/MICmdArgValOptionShort.cpp | 152 +- tools/lldb-mi/MICmdArgValOptionShort.h | 71 +- tools/lldb-mi/MICmdArgValString.cpp | 827 +++--- tools/lldb-mi/MICmdArgValString.h | 95 +- tools/lldb-mi/MICmdArgValThreadGrp.cpp | 243 +- tools/lldb-mi/MICmdArgValThreadGrp.h | 74 +- tools/lldb-mi/MICmdBase.cpp | 344 +-- tools/lldb-mi/MICmdBase.h | 218 +- tools/lldb-mi/MICmdCmd.cpp | 212 +- tools/lldb-mi/MICmdCmd.h | 117 +- tools/lldb-mi/MICmdCmdBreak.cpp | 1619 ++++++------ tools/lldb-mi/MICmdCmdBreak.h | 426 +-- tools/lldb-mi/MICmdCmdData.cpp | 2107 +++++++-------- tools/lldb-mi/MICmdCmdData.h | 596 +++-- tools/lldb-mi/MICmdCmdEnviro.cpp | 182 +- tools/lldb-mi/MICmdCmdEnviro.h | 75 +- tools/lldb-mi/MICmdCmdExec.cpp | 1341 +++++----- tools/lldb-mi/MICmdCmdExec.h | 475 ++-- tools/lldb-mi/MICmdCmdFile.cpp | 248 +- tools/lldb-mi/MICmdCmdFile.h | 81 +- tools/lldb-mi/MICmdCmdGdbInfo.cpp | 334 +-- tools/lldb-mi/MICmdCmdGdbInfo.h | 120 +- tools/lldb-mi/MICmdCmdGdbSet.cpp | 365 +-- tools/lldb-mi/MICmdCmdGdbSet.h | 132 +- tools/lldb-mi/MICmdCmdGdbThread.cpp | 115 +- tools/lldb-mi/MICmdCmdGdbThread.h | 68 +- tools/lldb-mi/MICmdCmdMiscellanous.cpp | 879 ++++--- tools/lldb-mi/MICmdCmdMiscellanous.h | 254 +- tools/lldb-mi/MICmdCmdStack.cpp | 958 +++---- tools/lldb-mi/MICmdCmdStack.h | 277 +- tools/lldb-mi/MICmdCmdSupportInfo.cpp | 156 +- tools/lldb-mi/MICmdCmdSupportInfo.h | 79 +- tools/lldb-mi/MICmdCmdSupportList.cpp | 115 +- tools/lldb-mi/MICmdCmdSupportList.h | 69 +- tools/lldb-mi/MICmdCmdTarget.cpp | 322 +-- tools/lldb-mi/MICmdCmdTarget.h | 78 +- tools/lldb-mi/MICmdCmdThread.cpp | 306 +-- tools/lldb-mi/MICmdCmdThread.h | 88 +- tools/lldb-mi/MICmdCmdTrace.cpp | 113 +- tools/lldb-mi/MICmdCmdTrace.h | 66 +- tools/lldb-mi/MICmdCmdVar.cpp | 2330 +++++++++-------- tools/lldb-mi/MICmdCmdVar.h | 602 +++-- tools/lldb-mi/MICmdCommands.cpp | 171 +- tools/lldb-mi/MICmdCommands.h | 25 +- tools/lldb-mi/MICmdData.cpp | 13 +- tools/lldb-mi/MICmdData.h | 93 +- tools/lldb-mi/MICmdFactory.cpp | 322 +-- tools/lldb-mi/MICmdFactory.h | 117 +- tools/lldb-mi/MICmdInterpreter.cpp | 442 ++-- tools/lldb-mi/MICmdInterpreter.h | 88 +- tools/lldb-mi/MICmdInvoker.cpp | 498 ++-- tools/lldb-mi/MICmdInvoker.h | 155 +- tools/lldb-mi/MICmdMgr.cpp | 358 +-- tools/lldb-mi/MICmdMgr.h | 90 +- tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp | 123 +- tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h | 86 +- tools/lldb-mi/MICmnBase.cpp | 178 +- tools/lldb-mi/MICmnBase.h | 66 +- tools/lldb-mi/MICmnConfig.h | 16 +- tools/lldb-mi/MICmnLLDBBroadcaster.cpp | 97 +- tools/lldb-mi/MICmnLLDBBroadcaster.h | 59 +- tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp | 2284 ++++++++-------- tools/lldb-mi/MICmnLLDBDebugSessionInfo.h | 379 +-- tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp | 859 +++--- tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h | 208 +- tools/lldb-mi/MICmnLLDBDebugger.cpp | 1097 ++++---- tools/lldb-mi/MICmnLLDBDebugger.h | 172 +- tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp | 2731 ++++++++++---------- tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h | 121 +- tools/lldb-mi/MICmnLLDBProxySBValue.cpp | 217 +- tools/lldb-mi/MICmnLLDBProxySBValue.h | 32 +- tools/lldb-mi/MICmnLLDBUtilSBValue.cpp | 460 ++-- tools/lldb-mi/MICmnLLDBUtilSBValue.h | 76 +- tools/lldb-mi/MICmnLog.cpp | 525 ++-- tools/lldb-mi/MICmnLog.h | 228 +- tools/lldb-mi/MICmnLogMediumFile.cpp | 590 +++-- tools/lldb-mi/MICmnLogMediumFile.h | 128 +- tools/lldb-mi/MICmnMIOutOfBandRecord.cpp | 210 +- tools/lldb-mi/MICmnMIOutOfBandRecord.h | 146 +- tools/lldb-mi/MICmnMIResultRecord.cpp | 174 +- tools/lldb-mi/MICmnMIResultRecord.h | 140 +- tools/lldb-mi/MICmnMIValue.cpp | 62 +- tools/lldb-mi/MICmnMIValue.h | 74 +- tools/lldb-mi/MICmnMIValueConst.cpp | 119 +- tools/lldb-mi/MICmnMIValueConst.h | 88 +- tools/lldb-mi/MICmnMIValueList.cpp | 276 +- tools/lldb-mi/MICmnMIValueList.h | 84 +- tools/lldb-mi/MICmnMIValueResult.cpp | 171 +- tools/lldb-mi/MICmnMIValueResult.h | 94 +- tools/lldb-mi/MICmnMIValueTuple.cpp | 315 +-- tools/lldb-mi/MICmnMIValueTuple.h | 92 +- tools/lldb-mi/MICmnResources.cpp | 699 ++--- tools/lldb-mi/MICmnResources.h | 623 +++-- tools/lldb-mi/MICmnStreamStderr.cpp | 350 +-- tools/lldb-mi/MICmnStreamStderr.h | 88 +- tools/lldb-mi/MICmnStreamStdin.cpp | 594 +++-- tools/lldb-mi/MICmnStreamStdin.h | 182 +- tools/lldb-mi/MICmnStreamStdinLinux.cpp | 307 +-- tools/lldb-mi/MICmnStreamStdinLinux.h | 87 +- tools/lldb-mi/MICmnStreamStdinWindows.cpp | 336 +-- tools/lldb-mi/MICmnStreamStdinWindows.h | 102 +- tools/lldb-mi/MICmnStreamStdout.cpp | 310 +-- tools/lldb-mi/MICmnStreamStdout.h | 86 +- tools/lldb-mi/MICmnThreadMgrStd.cpp | 224 +- tools/lldb-mi/MICmnThreadMgrStd.h | 202 +- tools/lldb-mi/MIDataTypes.h | 84 +- tools/lldb-mi/MIDriver.cpp | 1923 +++++++------- tools/lldb-mi/MIDriver.h | 290 +-- tools/lldb-mi/MIDriverBase.cpp | 239 +- tools/lldb-mi/MIDriverBase.h | 95 +- tools/lldb-mi/MIDriverMain.cpp | 540 ++-- tools/lldb-mi/MIDriverMgr.cpp | 1254 ++++----- tools/lldb-mi/MIDriverMgr.h | 201 +- tools/lldb-mi/MIUtilDateTimeStd.cpp | 89 +- tools/lldb-mi/MIUtilDateTimeStd.h | 56 +- tools/lldb-mi/MIUtilDebug.cpp | 131 +- tools/lldb-mi/MIUtilDebug.h | 104 +- tools/lldb-mi/MIUtilFileStd.cpp | 417 +-- tools/lldb-mi/MIUtilFileStd.h | 75 +- tools/lldb-mi/MIUtilMapIdToVariant.cpp | 145 +- tools/lldb-mi/MIUtilMapIdToVariant.h | 216 +- tools/lldb-mi/MIUtilSingletonBase.h | 79 +- tools/lldb-mi/MIUtilSingletonHelper.h | 115 +- tools/lldb-mi/MIUtilString.cpp | 1054 ++++---- tools/lldb-mi/MIUtilString.h | 108 +- tools/lldb-mi/MIUtilSystemLinux.cpp | 138 +- tools/lldb-mi/MIUtilSystemLinux.h | 56 +- tools/lldb-mi/MIUtilSystemOsx.cpp | 144 +- tools/lldb-mi/MIUtilSystemOsx.h | 56 +- tools/lldb-mi/MIUtilSystemWindows.cpp | 196 +- tools/lldb-mi/MIUtilSystemWindows.h | 56 +- tools/lldb-mi/MIUtilTermios.cpp | 54 +- tools/lldb-mi/MIUtilTermios.h | 16 +- tools/lldb-mi/MIUtilThreadBaseStd.cpp | 441 ++-- tools/lldb-mi/MIUtilThreadBaseStd.h | 251 +- tools/lldb-mi/MIUtilVariant.cpp | 474 ++-- tools/lldb-mi/MIUtilVariant.h | 393 +-- tools/lldb-mi/Platform.cpp | 69 +- tools/lldb-mi/Platform.h | 182 +- tools/lldb-platform/lldb-platform.cpp | 6 +- 668 files changed, 59878 insertions(+), 35726 deletions(-) create mode 100644 include/lldb/API/SBExecutionContext.h create mode 100644 include/lldb/API/SBThreadCollection.h create mode 100644 include/lldb/API/SBThreadPlan.h delete mode 100644 include/lldb/Core/ConnectionFileDescriptor.h create mode 100644 include/lldb/Core/ThreadSafeDenseMap.h create mode 100644 include/lldb/DataFormatters/StringPrinter.h create mode 100644 include/lldb/DataFormatters/TypeValidator.h create mode 100644 include/lldb/Expression/ClangModulesDeclVendor.h create mode 100644 include/lldb/Host/ConnectionFileDescriptor.h create mode 100644 include/lldb/Host/HostNativeProcess.h create mode 100644 include/lldb/Host/HostNativeProcessBase.h create mode 100644 include/lldb/Host/HostNativeThread.h create mode 100644 include/lldb/Host/HostNativeThreadBase.h create mode 100644 include/lldb/Host/HostNativeThreadForward.h create mode 100644 include/lldb/Host/HostThread.h create mode 100644 include/lldb/Host/MonitoringProcessLauncher.h create mode 100644 include/lldb/Host/PipeBase.h create mode 100644 include/lldb/Host/ProcessLauncher.h create mode 100644 include/lldb/Host/ThisThread.h create mode 100644 include/lldb/Host/ThreadLauncher.h create mode 100644 include/lldb/Host/freebsd/HostThreadFreeBSD.h create mode 100644 include/lldb/Host/posix/ConnectionFileDescriptorPosix.h create mode 100644 include/lldb/Host/posix/HostThreadPosix.h create mode 100644 include/lldb/Host/posix/PipePosix.h create mode 100644 include/lldb/Host/posix/ProcessLauncherPosix.h create mode 100644 include/lldb/Interpreter/OptionValueChar.h create mode 100644 include/lldb/Symbol/CompactUnwindInfo.h create mode 100644 include/lldb/Symbol/DeclVendor.h delete mode 100644 include/lldb/Symbol/TypeVendor.h create mode 100644 include/lldb/Target/InstrumentationRuntime.h create mode 100644 include/lldb/Target/InstrumentationRuntimeStopInfo.h create mode 100644 include/lldb/Target/MemoryHistory.h create mode 100644 include/lldb/Target/ThreadCollection.h create mode 100644 include/lldb/Target/ThreadPlanPython.h create mode 100644 include/lldb/Utility/ProcessStructReader.h create mode 100644 include/lldb/Utility/RegisterNumber.h create mode 100644 source/API/SBExecutionContext.cpp create mode 100644 source/API/SBThreadCollection.cpp create mode 100644 source/API/SBThreadPlan.cpp delete mode 100644 source/Core/ConnectionFileDescriptor.cpp create mode 100644 source/DataFormatters/LibCxxInitializerList.cpp create mode 100644 source/DataFormatters/LibCxxVector.cpp create mode 100644 source/DataFormatters/NSIndexPath.cpp create mode 100644 source/DataFormatters/StringPrinter.cpp create mode 100644 source/DataFormatters/TypeValidator.cpp create mode 100644 source/Expression/ClangModulesDeclVendor.cpp create mode 100644 source/Host/common/HostNativeThreadBase.cpp create mode 100644 source/Host/common/HostProcess.cpp create mode 100644 source/Host/common/HostThread.cpp create mode 100644 source/Host/common/MonitoringProcessLauncher.cpp delete mode 100644 source/Host/common/Pipe.cpp create mode 100644 source/Host/common/PipeBase.cpp create mode 100644 source/Host/common/ThisThread.cpp create mode 100644 source/Host/common/ThreadLauncher.cpp create mode 100644 source/Host/freebsd/HostThreadFreeBSD.cpp create mode 100644 source/Host/freebsd/ThisThread.cpp create mode 100644 source/Host/posix/ConnectionFileDescriptorPosix.cpp create mode 100644 source/Host/posix/HostThreadPosix.cpp create mode 100644 source/Host/posix/PipePosix.cpp create mode 100644 source/Host/posix/ProcessLauncherPosix.cpp create mode 100644 source/Interpreter/OptionValueChar.cpp create mode 100644 source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp create mode 100644 source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h create mode 100644 source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp create mode 100644 source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h create mode 100644 source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp create mode 100644 source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h create mode 100644 source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp create mode 100644 source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h create mode 100644 source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp create mode 100644 source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h create mode 100644 source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp create mode 100644 source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h create mode 100644 source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp create mode 100644 source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h create mode 100644 source/Plugins/Process/Utility/RegisterContext_powerpc.h create mode 100644 source/Plugins/Process/Utility/RegisterInfos_powerpc.h create mode 100644 source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp create mode 100644 source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h create mode 100644 source/Symbol/CompactUnwindInfo.cpp create mode 100644 source/Target/InstrumentationRuntime.cpp create mode 100644 source/Target/InstrumentationRuntimeStopInfo.cpp create mode 100644 source/Target/MemoryHistory.cpp create mode 100644 source/Target/ThreadCollection.cpp create mode 100644 source/Target/ThreadPlanPython.cpp create mode 100644 source/Utility/RegisterNumber.cpp create mode 100644 source/Utility/UriParser.cpp create mode 100644 source/Utility/UriParser.h create mode 100644 tools/compact-unwind/compact-unwind-dumper.c diff --git a/docs/lldb.1 b/docs/lldb.1 index 4929e91f937e..0d94dcbe6a78 100644 --- a/docs/lldb.1 +++ b/docs/lldb.1 @@ -1,7 +1,7 @@ -.Dd 7 June, 2012 \" DATE +.Dd June 7, 2012 \" DATE .Dt LLDB 1 \" Program name and manual section number .Os Darwin \" Operating System -.Sh NAME \" Section Header - required - don't modify +.Sh NAME \" Section Header - required - don't modify .Nm lldb .Nd The debugger .Sh SYNOPSIS \" Section Header - required - don't modify @@ -15,30 +15,30 @@ .Ar [[--] ...] .Sh DESCRIPTION \" Section Header - required - don't modify .Nm -is the command line interface for the LLDB debugger library. +is the command line interface for the LLDB debugger library. .Nm can debug C, C++, Objective-C, and Objective-C++ programs. .Pp The following options are available: .Bl -tag -width indent -.It Fl h, -help -Prints out the usage information for the +.It Fl h, -help +Prints out the usage information for the .Nm debugger. The \fB\-\-help\fR text may be more up-to-date and authoritative than the command line options described in this man page. -.It Fl v, -version -Prints out the version number of the -.Nm +.It Fl v, -version +Prints out the version number of the +.Nm debugger. .It Fl a, -arch Ar arch -Specifies which architecture +Specifies which architecture .Nm will use when launching the specified program (assuming the provided executable is built for multiple architectures.) .It Fl f, -file Ar filename Specifies the executable file that -.nm +.Nm will be launching / attaching to. .It Fl n, -attach-name Ar process-name Specifies the name of a currently-running process to attach to. @@ -60,10 +60,10 @@ Currently only the Python extensions have been implemented. .It Fl d, -debug Tells the debugger to print out extra information for debugging itself. .It Fl s, -source Ar filename -Tells +Tells .Nm to read in and execute the file "\fBfilename\fR", which -should contain +should contain .Nm commands. .It Fl e, -editor @@ -81,7 +81,7 @@ Remember to end the options with "--" if any of your arguments have a "-" in the In .Nm there is a \fBhelp\fR command which can be used to find descriptions and examples of -all +all .Nm commands. To get help on "\fBbreakpoint set\fR" you would type "\fBhelp breakpoint set\fR". .Pp @@ -94,18 +94,18 @@ will read settings/aliases/commands from three files at startup, if they exist. .Pp First, it will read a \fB~/.lldbinit-\fIdebugger\fR command file. If you are using the .Nm -command line interface, this is \fB~/.lldbinit-lldb\fR. If you are using +command line interface, this is \fB~/.lldbinit-lldb\fR. If you are using .Nm inside a GUI debugger like .Nm Xcode this will be \fB~/.lldbinit-Xcode\fR. This is a useful place to put settings that you -want to apply only when a given +want to apply only when a given .Nm command interpreter is used. .Pp Second, \fB~/.lldbinit\fR is read. .Pp -Third, an \fR.lldbinit\fR file in the current working directory (where +Third, an \fR.lldbinit\fR file in the current working directory (where .Nm is started) will be read. .Sh SEE ALSO diff --git a/include/lldb/API/LLDB.h b/include/lldb/API/LLDB.h index b9c3198b73e5..4026b2b61ba8 100644 --- a/include/lldb/API/LLDB.h +++ b/include/lldb/API/LLDB.h @@ -29,6 +29,7 @@ #include "lldb/API/SBDeclaration.h" #include "lldb/API/SBError.h" #include "lldb/API/SBEvent.h" +#include "lldb/API/SBExecutionContext.h" #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBFrame.h" #include "lldb/API/SBFunction.h" diff --git a/include/lldb/API/SBAddress.h b/include/lldb/API/SBAddress.h index 58a7d2bfb1da..c2d07b6e9bcc 100644 --- a/include/lldb/API/SBAddress.h +++ b/include/lldb/API/SBAddress.h @@ -117,6 +117,7 @@ protected: friend class SBSymbolContext; friend class SBTarget; friend class SBThread; + friend class SBThreadPlan; friend class SBValue; friend class SBQueueItem; diff --git a/include/lldb/API/SBBreakpoint.h b/include/lldb/API/SBBreakpoint.h index 86d49c29a821..20a97a1fb5a0 100644 --- a/include/lldb/API/SBBreakpoint.h +++ b/include/lldb/API/SBBreakpoint.h @@ -123,6 +123,18 @@ public: SBError SetScriptCallbackBody (const char *script_body_text); + + bool + AddName (const char *new_name); + + void + RemoveName (const char *name_to_remove); + + bool + MatchesName (const char *name); + + void + GetNames (SBStringList &names); size_t GetNumResolvedLocations() const; diff --git a/include/lldb/API/SBCommandInterpreter.h b/include/lldb/API/SBCommandInterpreter.h index 184a6b473126..947e39164140 100644 --- a/include/lldb/API/SBCommandInterpreter.h +++ b/include/lldb/API/SBCommandInterpreter.h @@ -15,6 +15,61 @@ namespace lldb { +class SBCommandInterpreterRunOptions +{ +friend class SBDebugger; +friend class SBCommandInterpreter; + +public: + SBCommandInterpreterRunOptions(); + ~SBCommandInterpreterRunOptions(); + + bool + GetStopOnContinue () const; + + void + SetStopOnContinue (bool); + + bool + GetStopOnError () const; + + void + SetStopOnError (bool); + + bool + GetStopOnCrash () const; + + void + SetStopOnCrash (bool); + + bool + GetEchoCommands () const; + + void + SetEchoCommands (bool); + + bool + GetPrintResults () const; + + void + SetPrintResults (bool); + + bool + GetAddToHistory () const; + + void + SetAddToHistory (bool); +private: + lldb_private::CommandInterpreterRunOptions * + get () const; + + lldb_private::CommandInterpreterRunOptions & + ref () const; + + // This is set in the constructor and will always be valid. + mutable std::unique_ptr m_opaque_up; +}; + class SBCommandInterpreter { public: @@ -85,6 +140,15 @@ public: lldb::ReturnStatus HandleCommand (const char *command_line, lldb::SBCommandReturnObject &result, bool add_to_history = false); + lldb::ReturnStatus + HandleCommand (const char *command_line, SBExecutionContext &exe_ctx, SBCommandReturnObject &result, bool add_to_history = false); + + void + HandleCommandsFromFile (lldb::SBFileSpec &file, + lldb::SBExecutionContext &override_context, + lldb::SBCommandInterpreterRunOptions &options, + lldb::SBCommandReturnObject result); + // The pointer based interface is not useful in SWIG, since the cursor & last_char arguments are string pointers INTO current_line // and you can't do that in a scripting language interface in general... @@ -175,9 +239,9 @@ class SBCommandPluginInterface { public: virtual bool - DoExecute (lldb::SBDebugger debugger, - char** command, - lldb::SBCommandReturnObject &result) + DoExecute (lldb::SBDebugger /*debugger*/, + char** /*command*/, + lldb::SBCommandReturnObject & /*result*/) { return false; } diff --git a/include/lldb/API/SBCompileUnit.h b/include/lldb/API/SBCompileUnit.h index 95af3d4722ce..e2c216445d94 100644 --- a/include/lldb/API/SBCompileUnit.h +++ b/include/lldb/API/SBCompileUnit.h @@ -78,6 +78,9 @@ public: lldb::SBTypeList GetTypes (uint32_t type_mask = lldb::eTypeClassAny); + lldb::LanguageType + GetLanguage (); + bool operator == (const lldb::SBCompileUnit &rhs) const; diff --git a/include/lldb/API/SBData.h b/include/lldb/API/SBData.h index 10c002247271..e7656a52d9c2 100644 --- a/include/lldb/API/SBData.h +++ b/include/lldb/API/SBData.h @@ -169,6 +169,7 @@ private: friend class SBInstruction; friend class SBProcess; friend class SBSection; + friend class SBTarget; friend class SBValue; lldb::DataExtractorSP m_opaque_sp; diff --git a/include/lldb/API/SBDebugger.h b/include/lldb/API/SBDebugger.h index 2386ffc968de..6e43e12f7b16 100644 --- a/include/lldb/API/SBDebugger.h +++ b/include/lldb/API/SBDebugger.h @@ -27,6 +27,7 @@ public: void SetIsDone(bool); bool IsActive() const; }; + class SBDebugger { public: @@ -321,6 +322,13 @@ public: RunCommandInterpreter (bool auto_handle_events, bool spawn_thread); + void + RunCommandInterpreter (bool auto_handle_events, + bool spawn_thread, + SBCommandInterpreterRunOptions &options, + int &num_errors, + bool &quit_requested, + bool &stopped_for_crash); private: friend class SBCommandInterpreter; diff --git a/include/lldb/API/SBDefines.h b/include/lldb/API/SBDefines.h index 30ea0dfda56e..b59b79580910 100644 --- a/include/lldb/API/SBDefines.h +++ b/include/lldb/API/SBDefines.h @@ -35,6 +35,7 @@ class LLDB_API SBBreakpointLocation; class LLDB_API SBBroadcaster; class LLDB_API SBCommand; class LLDB_API SBCommandInterpreter; +class LLDB_API SBCommandInterpreterRunOptions; class LLDB_API SBCommandPluginInterface; class LLDB_API SBCommandReturnObject; class LLDB_API SBCommunication; @@ -45,6 +46,7 @@ class LLDB_API SBDeclaration; class LLDB_API SBError; class LLDB_API SBEvent; class LLDB_API SBEventList; +class LLDB_API SBExecutionContext; class LLDB_API SBExpressionOptions; class LLDB_API SBFileSpec; class LLDB_API SBFileSpecList; @@ -70,14 +72,18 @@ class LLDB_API SBSymbolContext; class LLDB_API SBSymbolContextList; class LLDB_API SBTarget; class LLDB_API SBThread; +class LLDB_API SBThreadCollection; +class LLDB_API SBThreadPlan; class LLDB_API SBType; class LLDB_API SBTypeCategory; class LLDB_API SBTypeEnumMember; class LLDB_API SBTypeEnumMemberList; class LLDB_API SBTypeFilter; class LLDB_API SBTypeFormat; +class LLDB_API SBTypeMemberFunction; class LLDB_API SBTypeNameSpecifier; class LLDB_API SBTypeSummary; +class LLDB_API SBTypeSummaryOptions; #ifndef LLDB_DISABLE_PYTHON class LLDB_API SBTypeSynthetic; #endif diff --git a/include/lldb/API/SBEvent.h b/include/lldb/API/SBEvent.h index 6cb975a1ff7b..1706d0c009b9 100644 --- a/include/lldb/API/SBEvent.h +++ b/include/lldb/API/SBEvent.h @@ -30,6 +30,10 @@ public: // Make an event that contains a C string. SBEvent (uint32_t event, const char *cstr, uint32_t cstr_len); + SBEvent (lldb::EventSP &event_sp); + + SBEvent (lldb_private::Event *event_sp); + ~SBEvent(); const SBEvent & @@ -77,8 +81,6 @@ protected: friend class SBThread; friend class SBWatchpoint; - SBEvent (lldb::EventSP &event_sp); - lldb::EventSP & GetSP () const; diff --git a/include/lldb/API/SBExecutionContext.h b/include/lldb/API/SBExecutionContext.h new file mode 100644 index 000000000000..9d889139f5cb --- /dev/null +++ b/include/lldb/API/SBExecutionContext.h @@ -0,0 +1,74 @@ +//===-- SBExecutionContext.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SBExecutionContext_h_ +#define LLDB_SBExecutionContext_h_ + +#include "lldb/API/SBDefines.h" + +#include +#include + + +namespace lldb { + +class SBExecutionContext +{ +friend class SBCommandInterpreter; + +public: + SBExecutionContext(); + + SBExecutionContext (const lldb::SBExecutionContext &rhs); + + SBExecutionContext (lldb::ExecutionContextRefSP exe_ctx_ref_sp); + + SBExecutionContext (const lldb::SBTarget &target); + + SBExecutionContext (const lldb::SBProcess &process); + + SBExecutionContext (lldb::SBThread thread); // can't be a const& because SBThread::get() isn't itself a const function + + SBExecutionContext (const lldb::SBFrame &frame); + + ~SBExecutionContext(); + + const SBExecutionContext & + operator = (const lldb::SBExecutionContext &rhs); + + SBTarget + GetTarget () const; + + SBProcess + GetProcess () const; + + SBThread + GetThread () const; + + SBFrame + GetFrame () const; + +protected: + ExecutionContextRefSP & + GetSP () const; + + void + reset (lldb::ExecutionContextRefSP &event_sp); + + lldb_private::ExecutionContextRef * + get () const; + +private: + + mutable lldb::ExecutionContextRefSP m_exe_ctx_sp; +}; + +} // namespace lldb + +#endif // LLDB_SBExecutionContext_h_ diff --git a/include/lldb/API/SBFileSpec.h b/include/lldb/API/SBFileSpec.h index d262b98d0fd7..1eee3d10367c 100644 --- a/include/lldb/API/SBFileSpec.h +++ b/include/lldb/API/SBFileSpec.h @@ -63,6 +63,7 @@ public: private: friend class SBAttachInfo; friend class SBBlock; + friend class SBCommandInterpreter; friend class SBCompileUnit; friend class SBDeclaration; friend class SBFileSpecList; diff --git a/include/lldb/API/SBFrame.h b/include/lldb/API/SBFrame.h index f6b84ab1ddac..b93e36afecdf 100644 --- a/include/lldb/API/SBFrame.h +++ b/include/lldb/API/SBFrame.h @@ -198,21 +198,6 @@ public: lldb::SBValue FindValue (const char *name, ValueType value_type, lldb::DynamicValueType use_dynamic); - /// Find and watch a variable using the frame as the scope. - /// It returns an SBValue, similar to FindValue() method, if find-and-watch - /// operation succeeds. Otherwise, an invalid SBValue is returned. - /// You can use LLDB_WATCH_TYPE_READ | LLDB_WATCH_TYPE_WRITE for 'rw' watch. - lldb::SBValue - WatchValue (const char *name, ValueType value_type, uint32_t watch_type); - - /// Find and watch the location pointed to by a variable using the frame as - /// the scope. - /// It returns an SBValue, similar to FindValue() method, if find-and-watch - /// operation succeeds. Otherwise, an invalid SBValue is returned. - /// You can use LLDB_WATCH_TYPE_READ | LLDB_WATCH_TYPE_WRITE for 'rw' watch. - lldb::SBValue - WatchLocation (const char *name, ValueType value_type, uint32_t watch_type, size_t size); - bool GetDescription (lldb::SBStream &description); @@ -221,6 +206,7 @@ public: protected: friend class SBBlock; + friend class SBExecutionContext; friend class SBInstruction; friend class SBThread; friend class SBValue; diff --git a/include/lldb/API/SBFunction.h b/include/lldb/API/SBFunction.h index 49a3847efbec..1b0d53d11736 100644 --- a/include/lldb/API/SBFunction.h +++ b/include/lldb/API/SBFunction.h @@ -58,6 +58,9 @@ public: lldb::SBBlock GetBlock (); + + lldb::LanguageType + GetLanguage (); bool operator == (const lldb::SBFunction &rhs) const; diff --git a/include/lldb/API/SBListener.h b/include/lldb/API/SBListener.h index 4a11ec1072f1..58a8fe9a55b7 100644 --- a/include/lldb/API/SBListener.h +++ b/include/lldb/API/SBListener.h @@ -99,13 +99,23 @@ public: HandleBroadcastEvent (const lldb::SBEvent &event); protected: + friend class SBAttachInfo; friend class SBBroadcaster; friend class SBCommandInterpreter; friend class SBDebugger; + friend class SBLaunchInfo; friend class SBTarget; SBListener (lldb_private::Listener &listener); + SBListener (const lldb::ListenerSP &listener_sp); + + lldb::ListenerSP + GetSP () + { + return m_opaque_sp; + } + private: lldb_private::Listener * diff --git a/include/lldb/API/SBProcess.h b/include/lldb/API/SBProcess.h index 4b59462ca3f1..3d6e49c4821d 100644 --- a/include/lldb/API/SBProcess.h +++ b/include/lldb/API/SBProcess.h @@ -316,6 +316,12 @@ public: //------------------------------------------------------------------ const char * GetExtendedBacktraceTypeAtIndex (uint32_t idx); + + lldb::SBThreadCollection + GetHistoryThreads (addr_t addr); + + bool + IsInstrumentationRuntimePresent(InstrumentationRuntimeType type); protected: friend class SBAddress; @@ -323,6 +329,7 @@ protected: friend class SBBreakpointLocation; friend class SBCommandInterpreter; friend class SBDebugger; + friend class SBExecutionContext; friend class SBFunction; friend class SBModule; friend class SBTarget; diff --git a/include/lldb/API/SBSection.h b/include/lldb/API/SBSection.h index 3386484f6496..5a49049502fd 100644 --- a/include/lldb/API/SBSection.h +++ b/include/lldb/API/SBSection.h @@ -71,6 +71,18 @@ public: SectionType GetSectionType (); + //------------------------------------------------------------------ + /// Return the size of a target's byte represented by this section + /// in numbers of host bytes. Note that certain architectures have + /// varying minimum addressable unit (i.e. byte) size for their + /// CODE or DATA buses. + /// + /// @return + /// The number of host (8-bit) bytes needed to hold a target byte + //------------------------------------------------------------------ + uint32_t + GetTargetByteSize (); + bool operator == (const lldb::SBSection &rhs); diff --git a/include/lldb/API/SBStream.h b/include/lldb/API/SBStream.h index fb69c12f0a91..cd33bfda32ba 100644 --- a/include/lldb/API/SBStream.h +++ b/include/lldb/API/SBStream.h @@ -85,8 +85,10 @@ protected: friend class SBSymbolContextList; friend class SBTarget; friend class SBThread; + friend class SBThreadPlan; friend class SBType; friend class SBTypeEnumMember; + friend class SBTypeMemberFunction; friend class SBTypeMember; friend class SBValue; friend class SBWatchpoint; diff --git a/include/lldb/API/SBTarget.h b/include/lldb/API/SBTarget.h index 370d40d0454a..a628467caa43 100644 --- a/include/lldb/API/SBTarget.h +++ b/include/lldb/API/SBTarget.h @@ -22,6 +22,8 @@ namespace lldb { +class SBPlatform; + class SBLaunchInfo { public: @@ -49,7 +51,7 @@ public: SBFileSpec GetExecutableFile (); - + //---------------------------------------------------------------------- /// Set the executable file that will be used to launch the process and /// optionally set it as the first argument in the argument vector. @@ -75,7 +77,29 @@ public: //---------------------------------------------------------------------- void SetExecutableFile (SBFileSpec exe_file, bool add_as_first_arg); - + + + //---------------------------------------------------------------------- + /// Get the listener that will be used to receive process events. + /// + /// If no listener has been set via a call to + /// SBLaunchInfo::SetListener(), then an invalid SBListener will be + /// returned (SBListener::IsValid() will return false). If a listener + /// has been set, then the valid listener object will be returned. + //---------------------------------------------------------------------- + SBListener + GetListener (); + + //---------------------------------------------------------------------- + /// Set the listener that will be used to receive process events. + /// + /// By default the SBDebugger, which has a listener, that the SBTarget + /// belongs to will listen for the process events. Calling this function + /// allows a different listener to be used to listen for process events. + //---------------------------------------------------------------------- + void + SetListener (SBListener &listener); + uint32_t GetNumArguments (); @@ -256,7 +280,28 @@ public: bool ParentProcessIDIsValid(); - + + //---------------------------------------------------------------------- + /// Get the listener that will be used to receive process events. + /// + /// If no listener has been set via a call to + /// SBLaunchInfo::SetListener(), then an invalid SBListener will be + /// returned (SBListener::IsValid() will return false). If a listener + /// has been set, then the valid listener object will be returned. + //---------------------------------------------------------------------- + SBListener + GetListener (); + + //---------------------------------------------------------------------- + /// Set the listener that will be used to receive process events. + /// + /// By default the SBDebugger, which has a listener, that the SBTarget + /// belongs to will listen for the process events. Calling this function + /// allows a different listener to be used to listen for process events. + //---------------------------------------------------------------------- + void + SetListener (SBListener &listener); + protected: friend class SBTarget; @@ -308,6 +353,18 @@ public: lldb::SBProcess GetProcess (); + //------------------------------------------------------------------ + /// Return the platform object associated with the target. + /// + /// After return, the platform object should be checked for + /// validity. + /// + /// @return + /// A platform object. + //------------------------------------------------------------------ + lldb::SBPlatform + GetPlatform (); + //------------------------------------------------------------------ /// Install any binaries that need to be installed. /// @@ -563,6 +620,26 @@ public: const char * GetTriple (); + //------------------------------------------------------------------ + /// Architecture data byte width accessor + /// + /// @return + /// The size in 8-bit (host) bytes of a minimum addressable + /// unit from the Architecture's data bus + //------------------------------------------------------------------ + uint32_t + GetDataByteSize (); + + //------------------------------------------------------------------ + /// Architecture code byte width accessor + /// + /// @return + /// The size in 8-bit (host) bytes of a minimum addressable + /// unit from the Architecture's code bus + //------------------------------------------------------------------ + uint32_t + GetCodeByteSize (); + //------------------------------------------------------------------ /// Set the base load address for a module section. /// @@ -683,10 +760,61 @@ public: //------------------------------------------------------------------ lldb::SBValue FindFirstGlobalVariable (const char* name); + + //------------------------------------------------------------------ + /// Find global and static variables by pattern. + /// + /// @param[in] name + /// The pattern to search for global or static variables + /// + /// @param[in] max_matches + /// Allow the number of matches to be limited to \a max_matches. + /// + /// @param[in] matchtype + /// The match type to use. + /// + /// @return + /// A list of matched variables in an SBValueList. + //------------------------------------------------------------------ + lldb::SBValueList + FindGlobalVariables(const char *name, + uint32_t max_matches, + MatchType matchtype); + //------------------------------------------------------------------ + /// Find global functions by their name with pattern matching. + /// + /// @param[in] name + /// The pattern to search for global or static variables + /// + /// @param[in] max_matches + /// Allow the number of matches to be limited to \a max_matches. + /// + /// @param[in] matchtype + /// The match type to use. + /// + /// @return + /// A list of matched variables in an SBValueList. + //------------------------------------------------------------------ + lldb::SBSymbolContextList + FindGlobalFunctions(const char *name, + uint32_t max_matches, + MatchType matchtype); + void Clear (); + //------------------------------------------------------------------ + /// Resolve a current file address into a section offset address. + /// + /// @param[in] file_addr + /// + /// @return + /// An SBAddress which will be valid if... + //------------------------------------------------------------------ + lldb::SBAddress + ResolveFileAddress (lldb::addr_t file_addr); + //------------------------------------------------------------------ /// Resolve a current load address into a section offset address. /// @@ -732,6 +860,31 @@ public: ResolveSymbolContextForAddress (const SBAddress& addr, uint32_t resolve_scope); + //------------------------------------------------------------------ + /// Read target memory. If a target process is running then memory + /// is read from here. Otherwise the memory is read from the object + /// files. For a target whose bytes are sized as a multiple of host + /// bytes, the data read back will preserve the target's byte order. + /// + /// @param[in] addr + /// A target address to read from. + /// + /// @param[out] buf + /// The buffer to read memory into. + /// + /// @param[in] size + /// The maximum number of host bytes to read in the buffer passed + /// into this call + /// + /// @param[out] error + /// Error information is written here if the memory read fails. + /// + /// @return + /// The amount of data read in host bytes. + //------------------------------------------------------------------ + size_t + ReadMemory (const SBAddress addr, void *buf, size_t size, lldb::SBError &error); + lldb::SBBreakpoint BreakpointCreateByLocation (const char *file, uint32_t line); @@ -845,6 +998,12 @@ public: lldb::SBValue CreateValueFromAddress (const char *name, lldb::SBAddress addr, lldb::SBType type); + + lldb::SBValue + CreateValueFromData (const char *name, lldb::SBData data, lldb::SBType type); + + lldb::SBValue + CreateValueFromExpression (const char *name, const char* expr); SBSourceManager GetSourceManager(); @@ -893,6 +1052,7 @@ protected: friend class SBAddress; friend class SBBlock; friend class SBDebugger; + friend class SBExecutionContext; friend class SBFunction; friend class SBInstruction; friend class SBModule; diff --git a/include/lldb/API/SBThread.h b/include/lldb/API/SBThread.h index 07a43ebee7ce..db15f651f2d5 100644 --- a/include/lldb/API/SBThread.h +++ b/include/lldb/API/SBThread.h @@ -78,7 +78,10 @@ public: //-------------------------------------------------------------------------- uint64_t GetStopReasonDataAtIndex(uint32_t idx); - + + bool + GetStopReasonExtendedInfoAsJSON (lldb::SBStream &stream); + size_t GetStopDescription (char *dst, size_t dst_len); @@ -126,6 +129,9 @@ public: lldb::SBFileSpec &file_spec, uint32_t line); + SBError + StepUsingScriptedThreadPlan (const char *script_class_name); + SBError JumpToLine (lldb::SBFileSpec &file_spec, uint32_t line); @@ -216,9 +222,19 @@ public: bool SafeToCallFunctions (); +#ifndef SWIG + lldb_private::Thread * + operator->(); + + lldb_private::Thread * + get(); + +#endif + protected: friend class SBBreakpoint; friend class SBBreakpointLocation; + friend class SBExecutionContext; friend class SBFrame; friend class SBProcess; friend class SBDebugger; diff --git a/include/lldb/API/SBThreadCollection.h b/include/lldb/API/SBThreadCollection.h new file mode 100644 index 000000000000..b13cbd938e28 --- /dev/null +++ b/include/lldb/API/SBThreadCollection.h @@ -0,0 +1,68 @@ +//===-- SBThreadCollection.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SBThreadCollection_h_ +#define LLDB_SBThreadCollection_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBThreadCollection +{ +public: + + SBThreadCollection (); + + SBThreadCollection (const SBThreadCollection &rhs); + + const SBThreadCollection & + operator = (const SBThreadCollection &rhs); + + ~SBThreadCollection (); + + bool + IsValid () const; + + size_t + GetSize (); + + lldb::SBThread + GetThreadAtIndex (size_t idx); + +protected: + + // Mimic shared pointer... + lldb_private::ThreadCollection * + get() const; + + lldb_private::ThreadCollection * + operator->() const; + + lldb::ThreadCollectionSP & + operator*(); + + const lldb::ThreadCollectionSP & + operator*() const; + + SBThreadCollection (const lldb::ThreadCollectionSP &threads); + + void + SetOpaque (const lldb::ThreadCollectionSP &threads); + +private: + friend class SBProcess; + + lldb::ThreadCollectionSP m_opaque_sp; +}; + + +} // namespace lldb + +#endif // LLDB_SBThreadCollection_h_ diff --git a/include/lldb/API/SBThreadPlan.h b/include/lldb/API/SBThreadPlan.h new file mode 100644 index 000000000000..e53942d65fa8 --- /dev/null +++ b/include/lldb/API/SBThreadPlan.h @@ -0,0 +1,129 @@ +//===-- SBThread.h ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SBThreadPlan_h_ +#define LLDB_SBThreadPlan_h_ + +#include "lldb/API/SBDefines.h" + +#include + +namespace lldb { + +class SBThreadPlan +{ + +friend class lldb_private::ThreadPlan; + +public: + SBThreadPlan (); + + SBThreadPlan (const lldb::SBThreadPlan &threadPlan); + + SBThreadPlan (const lldb::ThreadPlanSP& lldb_object_sp); + + SBThreadPlan (lldb::SBThread &thread, const char *class_name); + + ~SBThreadPlan (); + + bool + IsValid() const; + + void + Clear (); + + lldb::StopReason + GetStopReason(); + + /// Get the number of words associated with the stop reason. + /// See also GetStopReasonDataAtIndex(). + size_t + GetStopReasonDataCount(); + + //-------------------------------------------------------------------------- + /// Get information associated with a stop reason. + /// + /// Breakpoint stop reasons will have data that consists of pairs of + /// breakpoint IDs followed by the breakpoint location IDs (they always come + /// in pairs). + /// + /// Stop Reason Count Data Type + /// ======================== ===== ========================================= + /// eStopReasonNone 0 + /// eStopReasonTrace 0 + /// eStopReasonBreakpoint N duple: {breakpoint id, location id} + /// eStopReasonWatchpoint 1 watchpoint id + /// eStopReasonSignal 1 unix signal number + /// eStopReasonException N exception data + /// eStopReasonExec 0 + /// eStopReasonPlanComplete 0 + //-------------------------------------------------------------------------- + uint64_t + GetStopReasonDataAtIndex(uint32_t idx); + + SBThread + GetThread () const; + + const lldb::SBThreadPlan & + operator = (const lldb::SBThreadPlan &rhs); + + bool + GetDescription (lldb::SBStream &description) const; + + void + SetPlanComplete (bool success); + + bool + IsPlanComplete(); + + bool + IsValid(); + + // This section allows an SBThreadPlan to push another of the common types of plans... + SBThreadPlan + QueueThreadPlanForStepOverRange (SBAddress &start_address, + lldb::addr_t range_size); + + SBThreadPlan + QueueThreadPlanForStepInRange (SBAddress &start_address, + lldb::addr_t range_size); + + SBThreadPlan + QueueThreadPlanForStepOut (uint32_t frame_idx_to_step_to, bool first_insn = false); + + SBThreadPlan + QueueThreadPlanForRunToAddress (SBAddress address); + +#ifndef SWIG + lldb_private::ThreadPlan * + get(); +#endif + +protected: + friend class SBBreakpoint; + friend class SBBreakpointLocation; + friend class SBFrame; + friend class SBProcess; + friend class SBDebugger; + friend class SBValue; + friend class lldb_private::QueueImpl; + friend class SBQueueItem; + +#ifndef SWIG + void + SetThreadPlan (const lldb::ThreadPlanSP& lldb_object_sp); +#endif + +private: + lldb::ThreadPlanSP m_opaque_sp; +}; + +} // namespace lldb + +#endif // LLDB_SBThreadPlan_h_ diff --git a/include/lldb/API/SBType.h b/include/lldb/API/SBType.h index 363aa59e35aa..303ddff6dc09 100644 --- a/include/lldb/API/SBType.h +++ b/include/lldb/API/SBType.h @@ -67,6 +67,59 @@ protected: std::unique_ptr m_opaque_ap; }; + +class SBTypeMemberFunction +{ +public: + SBTypeMemberFunction (); + + SBTypeMemberFunction (const lldb::SBTypeMemberFunction& rhs); + + ~SBTypeMemberFunction(); + + lldb::SBTypeMemberFunction& + operator = (const lldb::SBTypeMemberFunction& rhs); + + bool + IsValid() const; + + const char * + GetName (); + + lldb::SBType + GetType (); + + lldb::SBType + GetReturnType (); + + uint32_t + GetNumberOfArguments (); + + lldb::SBType + GetArgumentTypeAtIndex (uint32_t); + + lldb::MemberFunctionKind + GetKind(); + + bool + GetDescription (lldb::SBStream &description, + lldb::DescriptionLevel description_level); + +protected: + friend class SBType; + + void + reset (lldb_private::TypeMemberFunctionImpl *); + + lldb_private::TypeMemberFunctionImpl & + ref (); + + const lldb_private::TypeMemberFunctionImpl & + ref () const; + + lldb::TypeMemberFunctionImplSP m_opaque_sp; +}; + class SBType { @@ -96,6 +149,12 @@ public: bool IsPolymorphicClass (); + bool + IsArrayType (); + + bool + IsTypedefType (); + lldb::SBType GetPointerType(); @@ -113,6 +172,9 @@ public: lldb::SBType GetUnqualifiedType(); + + lldb::SBType + GetArrayElementType (); lldb::SBType GetCanonicalType(); @@ -160,6 +222,12 @@ public: lldb::SBTypeList GetFunctionArgumentTypes (); + + uint32_t + GetNumberOfMemberFunctions (); + + lldb::SBTypeMemberFunction + GetMemberFunctionAtIndex (uint32_t idx); const char* GetName(); @@ -172,6 +240,9 @@ public: bool IsTypeComplete (); + + uint32_t + GetTypeFlags (); bool GetDescription (lldb::SBStream &description, @@ -209,6 +280,7 @@ protected: friend class SBTypeEnumMemberList; friend class SBTypeNameSpecifier; friend class SBTypeMember; + friend class SBTypeMemberFunction; friend class SBTypeList; friend class SBValue; diff --git a/include/lldb/API/SBTypeSummary.h b/include/lldb/API/SBTypeSummary.h index 67a8607511cc..220451e6d70b 100644 --- a/include/lldb/API/SBTypeSummary.h +++ b/include/lldb/API/SBTypeSummary.h @@ -15,6 +15,56 @@ #ifndef LLDB_DISABLE_PYTHON namespace lldb { + class SBTypeSummaryOptions + { + public: + SBTypeSummaryOptions(); + + SBTypeSummaryOptions (const lldb::SBTypeSummaryOptions &rhs); + + SBTypeSummaryOptions (const lldb_private::TypeSummaryOptions *lldb_object_ptr); + + ~SBTypeSummaryOptions (); + + bool + IsValid (); + + lldb::LanguageType + GetLanguage (); + + lldb::TypeSummaryCapping + GetCapping (); + + void + SetLanguage (lldb::LanguageType); + + void + SetCapping (lldb::TypeSummaryCapping); + + protected: + friend class SBValue; + + lldb_private::TypeSummaryOptions * + operator->(); + + const lldb_private::TypeSummaryOptions * + operator->() const; + + lldb_private::TypeSummaryOptions * + get (); + + lldb_private::TypeSummaryOptions & + ref(); + + const lldb_private::TypeSummaryOptions & + ref() const; + + void + SetOptions (const lldb_private::TypeSummaryOptions *lldb_object_ptr); + + private: + std::unique_ptr m_opaque_ap; + }; class SBTypeSummary { diff --git a/include/lldb/API/SBValue.h b/include/lldb/API/SBValue.h index 93b869ba9c5c..bedac4ef1d2d 100644 --- a/include/lldb/API/SBValue.h +++ b/include/lldb/API/SBValue.h @@ -90,9 +90,16 @@ public: const char * GetSummary (); + const char * + GetSummary (lldb::SBStream& stream, + lldb::SBTypeSummaryOptions& options); + const char * GetObjectDescription (); + const char * + GetTypeValidatorResult (); + lldb::SBValue GetDynamicValue (lldb::DynamicValueType use_dynamic); @@ -152,6 +159,7 @@ public: lldb::SBValue CreateChildAtOffset (const char *name, uint32_t offset, lldb::SBType type); + // Deprecated - use the expression evaluator to perform type casting lldb::SBValue Cast (lldb::SBType type); @@ -345,6 +353,9 @@ public: lldb::SBType GetType(); + + lldb::SBValue + Persist (); bool GetDescription (lldb::SBStream &description); diff --git a/include/lldb/API/SBValueList.h b/include/lldb/API/SBValueList.h index b9a6aedea3cb..812fdac91c11 100644 --- a/include/lldb/API/SBValueList.h +++ b/include/lldb/API/SBValueList.h @@ -43,6 +43,9 @@ public: lldb::SBValue GetValueAtIndex (uint32_t idx) const; + + lldb::SBValue + GetFirstValueByName (const char* name) const; lldb::SBValue FindValueObjectByUID (lldb::user_id_t uid); diff --git a/include/lldb/Breakpoint/Breakpoint.h b/include/lldb/Breakpoint/Breakpoint.h index 15693f86e382..61acc061aebc 100644 --- a/include/lldb/Breakpoint/Breakpoint.h +++ b/include/lldb/Breakpoint/Breakpoint.h @@ -12,8 +12,11 @@ // C Includes // C++ Includes +#include + // Other libraries and framework includes // Project includes +#include "lldb/Breakpoint/BreakpointID.h" #include "lldb/Breakpoint/BreakpointLocationList.h" #include "lldb/Breakpoint/BreakpointOptions.h" #include "lldb/Breakpoint/BreakpointLocationCollection.h" @@ -203,13 +206,28 @@ public: /// Tell this breakpoint to scan a given module list and resolve any /// new locations that match the breakpoint's specifications. /// - /// @param[in] changed_modules + /// @param[in] module_list /// The list of modules to look in for new locations. + /// + /// @param[in] send_event + /// If \b true, send a breakpoint location added event for non-internal breakpoints. //------------------------------------------------------------------ void - ResolveBreakpointInModules (ModuleList &changed_modules); - + ResolveBreakpointInModules (ModuleList &module_list, bool send_event = true); + //------------------------------------------------------------------ + /// Tell this breakpoint to scan a given module list and resolve any + /// new locations that match the breakpoint's specifications. + /// + /// @param[in] changed_modules + /// The list of modules to look in for new locations. + /// + /// @param[in] new_locations + /// Fills new_locations with the new locations that were made. + //------------------------------------------------------------------ + void + ResolveBreakpointInModules (ModuleList &module_list, BreakpointLocationCollection &new_locations); + //------------------------------------------------------------------ /// Like ResolveBreakpointInModules, but allows for "unload" events, in /// which case we will remove any locations that are in modules that got @@ -538,10 +556,19 @@ public: /// This breakpoint's Target. //------------------------------------------------------------------ Target & - GetTarget (); + GetTarget () + { + return m_target; + } const Target & - GetTarget () const; + GetTarget () const + { + return m_target; + } + + const lldb::TargetSP + GetTargetSP (); void GetResolverDescription (Stream *s); @@ -600,6 +627,44 @@ public: return m_hardware; } + lldb::BreakpointResolverSP + GetResolver() + { + return m_resolver_sp; + } + + lldb::SearchFilterSP + GetSearchFilter() + { + return m_filter_sp; + } + + bool + AddName (const char *new_name, Error &error); + + void + RemoveName (const char *name_to_remove) + { + if (name_to_remove) + m_name_list.erase(name_to_remove); + } + + bool + MatchesName (const char *name) + { + return m_name_list.find(name) != m_name_list.end(); + } + + void + GetNames (std::vector &names) + { + names.clear(); + for (auto name : m_name_list) + { + names.push_back(name); + } + } + protected: friend class Target; //------------------------------------------------------------------ @@ -650,12 +715,18 @@ protected: IgnoreCountShouldStop (); private: + // This one should only be used by Target to copy breakpoints from target to target - primarily from the dummy + // target to prime new targets. + Breakpoint (Target &new_target, + Breakpoint &bp_to_copy_from); + //------------------------------------------------------------------ // For Breakpoint only //------------------------------------------------------------------ bool m_being_created; bool m_hardware; // If this breakpoint is required to use a hardware breakpoint Target &m_target; // The target that holds this breakpoint. + std::unordered_set m_name_list; // If not empty, this is the name of this breakpoint (many breakpoints can share the same name.) lldb::SearchFilterSP m_filter_sp; // The filter that constrains the breakpoint's domain. lldb::BreakpointResolverSP m_resolver_sp; // The resolver that defines this breakpoint. BreakpointOptions m_options; // Settable breakpoint options diff --git a/include/lldb/Breakpoint/BreakpointID.h b/include/lldb/Breakpoint/BreakpointID.h index 9e352100b9e1..5ca09634ee09 100644 --- a/include/lldb/Breakpoint/BreakpointID.h +++ b/include/lldb/Breakpoint/BreakpointID.h @@ -92,6 +92,21 @@ public: ParseCanonicalReference (const char *input, lldb::break_id_t *break_id, lldb::break_id_t *break_loc_id); + //------------------------------------------------------------------ + /// Takes an input string and checks to see whether it is a breakpoint name. + /// If it is a mal-formed breakpoint name, error will be set to an appropriate + /// error string. + /// + /// @param[in] input + /// A string containing JUST the breakpoint description. + /// @param[out] error + /// If the name is a well-formed breakpoint name, set to success, otherwise set to an error. + /// @return + /// \b true if the name is a breakpoint name (as opposed to an ID or range) false otherwise. + //------------------------------------------------------------------ + static bool + StringIsBreakpointName (const char *name, Error &error); + //------------------------------------------------------------------ /// Takes a breakpoint ID and the breakpoint location id and returns /// a string containing the canonical description for the breakpoint diff --git a/include/lldb/Breakpoint/BreakpointIDList.h b/include/lldb/Breakpoint/BreakpointIDList.h index c9fcef0a783c..c42787066617 100644 --- a/include/lldb/Breakpoint/BreakpointIDList.h +++ b/include/lldb/Breakpoint/BreakpointIDList.h @@ -68,7 +68,7 @@ public: StringContainsIDRangeExpression (const char *in_string, size_t *range_start_len, size_t *range_end_pos); static void - FindAndReplaceIDRanges (Args &old_args, Target *target, CommandReturnObject &result, Args &new_args); + FindAndReplaceIDRanges (Args &old_args, Target *target, bool allow_locations, CommandReturnObject &result, Args &new_args); private: BreakpointIDArray m_breakpoint_ids; diff --git a/include/lldb/Breakpoint/BreakpointList.h b/include/lldb/Breakpoint/BreakpointList.h index 27f80d0ffe09..f4837e1ce956 100644 --- a/include/lldb/Breakpoint/BreakpointList.h +++ b/include/lldb/Breakpoint/BreakpointList.h @@ -204,11 +204,25 @@ protected: bp_collection::const_iterator GetBreakpointIDConstIterator(lldb::break_id_t breakID) const; + Mutex & + GetMutex () const + { + return m_mutex; + } + mutable Mutex m_mutex; bp_collection m_breakpoints; // The breakpoint list, currently a list. lldb::break_id_t m_next_break_id; bool m_is_internal; +public: + typedef LockingAdaptedIterable BreakpointIterable; + BreakpointIterable + Breakpoints() + { + return BreakpointIterable(m_breakpoints, GetMutex()); + } + private: DISALLOW_COPY_AND_ASSIGN (BreakpointList); }; diff --git a/include/lldb/Breakpoint/BreakpointLocation.h b/include/lldb/Breakpoint/BreakpointLocation.h index ac4c28bb6e5f..8d5ebce411df 100644 --- a/include/lldb/Breakpoint/BreakpointLocation.h +++ b/include/lldb/Breakpoint/BreakpointLocation.h @@ -52,7 +52,6 @@ class BreakpointLocation : public StoppointLocation { public: - ~BreakpointLocation (); //------------------------------------------------------------------ @@ -374,7 +373,21 @@ public: m_is_reexported = is_reexported; } + //------------------------------------------------------------------ + /// Returns whether the two breakpoint locations might represent "equivalent locations". + /// This is used when modules changed to determine if a Location in the old module might + /// be the "same as" the input location. + /// + /// @param[in] location + /// The location to compare against. + /// + /// @return + /// \b true or \b false as given in the description above. + //------------------------------------------------------------------ + bool EquivalentToLocation(BreakpointLocation &location); + protected: + friend class BreakpointSite; friend class BreakpointLocationList; friend class Process; @@ -396,8 +409,14 @@ protected: bool IgnoreCountShouldStop(); - + private: + void + SwapLocation (lldb::BreakpointLocationSP swap_from); + + void + BumpHitCount(); + //------------------------------------------------------------------ // Constructors and Destructors diff --git a/include/lldb/Breakpoint/BreakpointLocationCollection.h b/include/lldb/Breakpoint/BreakpointLocationCollection.h index 7f6a659323be..004f8395122b 100644 --- a/include/lldb/Breakpoint/BreakpointLocationCollection.h +++ b/include/lldb/Breakpoint/BreakpointLocationCollection.h @@ -16,6 +16,7 @@ // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" +#include "lldb/Utility/Iterable.h" namespace lldb_private { @@ -202,6 +203,14 @@ private: collection m_break_loc_collection; +public: + typedef AdaptedIterable BreakpointLocationCollectionIterable; + BreakpointLocationCollectionIterable + BreakpointLocations() + { + return BreakpointLocationCollectionIterable(m_break_loc_collection); + } + }; } // namespace lldb_private diff --git a/include/lldb/Breakpoint/BreakpointLocationList.h b/include/lldb/Breakpoint/BreakpointLocationList.h index 0d8062eb644c..f67ef89ad705 100644 --- a/include/lldb/Breakpoint/BreakpointLocationList.h +++ b/include/lldb/Breakpoint/BreakpointLocationList.h @@ -19,6 +19,7 @@ #include "lldb/lldb-private.h" #include "lldb/Core/Address.h" #include "lldb/Host/Mutex.h" +#include "lldb/Utility/Iterable.h" namespace lldb_private { @@ -248,12 +249,18 @@ protected: AddLocation (const Address &addr, bool resolve_indirect_symbols, bool *new_location = NULL); + + void + SwapLocation (lldb::BreakpointLocationSP to_location_sp, lldb::BreakpointLocationSP from_location_sp); bool RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp); void RemoveInvalidLocations (const ArchSpec &arch); + + void + Compact(); typedef std::vector collection; typedef std::map BreakpointLocationIterable; + BreakpointLocationIterable + BreakpointLocations() + { + return BreakpointLocationIterable(m_locations); + } + }; } // namespace lldb_private diff --git a/include/lldb/Breakpoint/BreakpointResolver.h b/include/lldb/Breakpoint/BreakpointResolver.h index 184bdc950cbc..6ba53ea92f36 100644 --- a/include/lldb/Breakpoint/BreakpointResolver.h +++ b/include/lldb/Breakpoint/BreakpointResolver.h @@ -44,6 +44,8 @@ namespace lldb_private { class BreakpointResolver : public Searcher { +friend class Breakpoint; + public: //------------------------------------------------------------------ /// The breakpoint resolver need to have a breakpoint for "ResolveBreakpoint @@ -122,7 +124,8 @@ public: AddressResolver, // This is an instance of BreakpointResolverAddress NameResolver, // This is an instance of BreakpointResolverName FileRegexResolver, - ExceptionResolver + ExceptionResolver, + LastKnownResolverType = ExceptionResolver }; //------------------------------------------------------------------ @@ -133,6 +136,9 @@ public: return SubclassID; } + virtual lldb::BreakpointResolverSP + CopyForBreakpoint (Breakpoint &breakpoint) = 0; + protected: //------------------------------------------------------------------ /// SetSCMatchesByLine - Takes a symbol context list of matches which supposedly represent the same file and diff --git a/include/lldb/Breakpoint/BreakpointResolverAddress.h b/include/lldb/Breakpoint/BreakpointResolverAddress.h index 4ca4a405957e..c8f034d7345b 100644 --- a/include/lldb/Breakpoint/BreakpointResolverAddress.h +++ b/include/lldb/Breakpoint/BreakpointResolverAddress.h @@ -34,27 +34,27 @@ public: virtual ~BreakpointResolverAddress (); - virtual void - ResolveBreakpoint (SearchFilter &filter); + void + ResolveBreakpoint (SearchFilter &filter) override; - virtual void + void ResolveBreakpointInModules (SearchFilter &filter, - ModuleList &modules); + ModuleList &modules) override; - virtual Searcher::CallbackReturn + Searcher::CallbackReturn SearchCallback (SearchFilter &filter, SymbolContext &context, Address *addr, - bool containing); + bool containing) override; - virtual Searcher::Depth - GetDepth (); + Searcher::Depth + GetDepth () override; - virtual void - GetDescription (Stream *s); + void + GetDescription (Stream *s) override; - virtual void - Dump (Stream *s) const; + void + Dump (Stream *s) const override; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const BreakpointResolverAddress *) { return true; } @@ -62,6 +62,9 @@ public: return V->getResolverID() == BreakpointResolver::AddressResolver; } + lldb::BreakpointResolverSP + CopyForBreakpoint (Breakpoint &breakpoint) override; + protected: Address m_addr; diff --git a/include/lldb/Breakpoint/BreakpointResolverFileLine.h b/include/lldb/Breakpoint/BreakpointResolverFileLine.h index cc1633ce1705..cd62bcd032b0 100644 --- a/include/lldb/Breakpoint/BreakpointResolverFileLine.h +++ b/include/lldb/Breakpoint/BreakpointResolverFileLine.h @@ -37,20 +37,20 @@ public: virtual ~BreakpointResolverFileLine (); - virtual Searcher::CallbackReturn + Searcher::CallbackReturn SearchCallback (SearchFilter &filter, SymbolContext &context, Address *addr, - bool containing); + bool containing) override; - virtual Searcher::Depth - GetDepth (); + Searcher::Depth + GetDepth () override; - virtual void - GetDescription (Stream *s); + void + GetDescription (Stream *s) override; - virtual void - Dump (Stream *s) const; + void + Dump (Stream *s) const override; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const BreakpointResolverFileLine *) { return true; } @@ -58,6 +58,9 @@ public: return V->getResolverID() == BreakpointResolver::FileLineResolver; } + lldb::BreakpointResolverSP + CopyForBreakpoint (Breakpoint &breakpoint) override; + protected: friend class Breakpoint; FileSpec m_file_spec; // This is the file spec we are looking for. diff --git a/include/lldb/Breakpoint/BreakpointResolverFileRegex.h b/include/lldb/Breakpoint/BreakpointResolverFileRegex.h index f1c2b1409e92..2c05ac1c87da 100644 --- a/include/lldb/Breakpoint/BreakpointResolverFileRegex.h +++ b/include/lldb/Breakpoint/BreakpointResolverFileRegex.h @@ -34,20 +34,20 @@ public: virtual ~BreakpointResolverFileRegex (); - virtual Searcher::CallbackReturn + Searcher::CallbackReturn SearchCallback (SearchFilter &filter, SymbolContext &context, Address *addr, - bool containing); + bool containing) override; - virtual Searcher::Depth - GetDepth (); + Searcher::Depth + GetDepth () override; - virtual void - GetDescription (Stream *s); + void + GetDescription (Stream *s) override; - virtual void - Dump (Stream *s) const; + void + Dump (Stream *s) const override; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const BreakpointResolverFileRegex *) { return true; } @@ -55,6 +55,9 @@ public: return V->getResolverID() == BreakpointResolver::FileRegexResolver; } + lldb::BreakpointResolverSP + CopyForBreakpoint (Breakpoint &breakpoint) override; + protected: friend class Breakpoint; RegularExpression m_regex; // This is the line expression that we are looking for. diff --git a/include/lldb/Breakpoint/BreakpointResolverName.h b/include/lldb/Breakpoint/BreakpointResolverName.h index f481aa9c5338..c2a5b180f289 100644 --- a/include/lldb/Breakpoint/BreakpointResolverName.h +++ b/include/lldb/Breakpoint/BreakpointResolverName.h @@ -64,20 +64,20 @@ public: virtual ~BreakpointResolverName (); - virtual Searcher::CallbackReturn + Searcher::CallbackReturn SearchCallback (SearchFilter &filter, SymbolContext &context, Address *addr, - bool containing); + bool containing) override; - virtual Searcher::Depth - GetDepth (); + Searcher::Depth + GetDepth () override; - virtual void - GetDescription (Stream *s); + void + GetDescription (Stream *s) override; - virtual void - Dump (Stream *s) const; + void + Dump (Stream *s) const override; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const BreakpointResolverName *) { return true; } @@ -85,7 +85,12 @@ public: return V->getResolverID() == BreakpointResolver::NameResolver; } + lldb::BreakpointResolverSP + CopyForBreakpoint (Breakpoint &breakpoint) override; + protected: + BreakpointResolverName(const BreakpointResolverName &rhs); + struct LookupInfo { ConstString name; @@ -113,8 +118,6 @@ protected: void AddNameLookup (const ConstString &name, uint32_t name_type_mask); -private: - DISALLOW_COPY_AND_ASSIGN(BreakpointResolverName); }; } // namespace lldb_private diff --git a/include/lldb/Breakpoint/BreakpointSite.h b/include/lldb/Breakpoint/BreakpointSite.h index 1d2cbea18f9f..c6dbef781f22 100644 --- a/include/lldb/Breakpoint/BreakpointSite.h +++ b/include/lldb/Breakpoint/BreakpointSite.h @@ -259,6 +259,12 @@ public: private: friend class Process; friend class BreakpointLocation; + // The StopInfoBreakpoint knows when it is processing a hit for a thread for a site, so let it be the + // one to manage setting the location hit count once and only once. + friend class StopInfoBreakpoint; + + void + BumpHitCounts(); //------------------------------------------------------------------ /// The method removes the owner at \a break_loc_id from this breakpoint list. diff --git a/include/lldb/Core/Address.h b/include/lldb/Core/Address.h index 8dd2339f9207..b430ef7cec21 100644 --- a/include/lldb/Core/Address.h +++ b/include/lldb/Core/Address.h @@ -87,6 +87,7 @@ public: ///< and file and line), to information about what the pointer points to ///< if the address is in a section (section of pointers, c strings, etc). DumpStyleResolvedDescriptionNoModule, + DumpStyleResolvedDescriptionNoFunctionArguments, DumpStyleDetailedSymbolContext, ///< Detailed symbol context information for an address for all symbol ///< context members. DumpStyleResolvedPointerDescription ///< Dereference a pointer at the current address and then lookup the diff --git a/include/lldb/Core/ArchSpec.h b/include/lldb/Core/ArchSpec.h index 255beee573b6..694e204cdc0d 100644 --- a/include/lldb/Core/ArchSpec.h +++ b/include/lldb/Core/ArchSpec.h @@ -104,7 +104,6 @@ public: eCore_uknownMach32, eCore_uknownMach64, - eCore_kalimba, eCore_kalimba3, eCore_kalimba4, eCore_kalimba5, @@ -142,10 +141,12 @@ public: kCore_hexagon_first = eCore_hexagon_generic, kCore_hexagon_last = eCore_hexagon_hexagonv5, - kCore_kalimba_first = eCore_kalimba, + kCore_kalimba_first = eCore_kalimba3, kCore_kalimba_last = eCore_kalimba5 }; + typedef void (* StopInfoOverrideCallbackType)(lldb_private::Thread &thread); + //------------------------------------------------------------------ /// Default constructor. /// @@ -459,6 +460,30 @@ public: bool IsCompatibleMatch (const ArchSpec& rhs) const; + //------------------------------------------------------------------ + /// Get a stop info override callback for the current architecture. + /// + /// Most platform specific code should go in lldb_private::Platform, + /// but there are cases where no matter which platform you are on + /// certain things hold true. + /// + /// This callback is currently intended to handle cases where a + /// program stops at an instruction that won't get executed and it + /// allows the stop reasonm, like "breakpoint hit", to be replaced + /// with a different stop reason like "no stop reason". + /// + /// This is specifically used for ARM in Thumb code when we stop in + /// an IT instruction (if/then/else) where the instruction won't get + /// executed and therefore it wouldn't be correct to show the program + /// stopped at the current PC. The code is generic and applies to all + /// ARM CPUs. + /// + /// @return NULL or a valid stop info override callback for the + /// current architecture. + //------------------------------------------------------------------ + StopInfoOverrideCallbackType + GetStopInfoOverrideCallback () const; + protected: bool IsEqualTo (const ArchSpec& rhs, bool exact_match) const; diff --git a/include/lldb/Core/Communication.h b/include/lldb/Core/Communication.h index 7e8209d7d9c6..49532fe123c5 100644 --- a/include/lldb/Core/Communication.h +++ b/include/lldb/Core/Communication.h @@ -12,6 +12,7 @@ // C Includes // C++ Includes +#include #include // Other libraries and framework includes @@ -19,6 +20,7 @@ #include "lldb/lldb-private.h" #include "lldb/Core/Broadcaster.h" #include "lldb/Core/Error.h" +#include "lldb/Host/HostThread.h" #include "lldb/Host/Mutex.h" #include "lldb/lldb-private.h" @@ -350,8 +352,8 @@ private: protected: lldb::ConnectionSP m_connection_sp; ///< The connection that is current in use by this communications class. - lldb::thread_t m_read_thread; ///< The read thread handle in case we need to cancel the thread. - bool m_read_thread_enabled; + HostThread m_read_thread; ///< The read thread handle in case we need to cancel the thread. + std::atomic m_read_thread_enabled; std::string m_bytes; ///< A buffer to cache bytes read in the ReadThread function. Mutex m_bytes_mutex; ///< A mutex to protect multi-threaded access to the cached bytes. Mutex m_write_mutex; ///< Don't let multiple threads write at the same time... diff --git a/include/lldb/Core/Connection.h b/include/lldb/Core/Connection.h index dde3c4b1022c..775e0c846f85 100644 --- a/include/lldb/Core/Connection.h +++ b/include/lldb/Core/Connection.h @@ -46,6 +46,8 @@ public: virtual ~Connection (); + static Connection *CreateDefaultConnection(const char *url); + //------------------------------------------------------------------ /// Connect using the connect string \a url. /// diff --git a/include/lldb/Core/ConnectionFileDescriptor.h b/include/lldb/Core/ConnectionFileDescriptor.h deleted file mode 100644 index 75d0202fcf6c..000000000000 --- a/include/lldb/Core/ConnectionFileDescriptor.h +++ /dev/null @@ -1,118 +0,0 @@ -//===-- ConnectionFileDescriptor.h ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ConnectionFileDescriptor_h_ -#define liblldb_ConnectionFileDescriptor_h_ - -// C++ Includes -#include - -#include "lldb/lldb-forward.h" - -// Other libraries and framework includes -// Project includes -#include "lldb/Core/Connection.h" -#include "lldb/Host/Mutex.h" -#include "lldb/Host/Pipe.h" -#include "lldb/Host/Predicate.h" -#include "lldb/Host/IOObject.h" - -namespace lldb_private { - -class Error; -class Socket; -class SocketAddress; - -class ConnectionFileDescriptor : - public Connection -{ -public: - - ConnectionFileDescriptor (); - - ConnectionFileDescriptor (int fd, bool owns_fd); - - virtual - ~ConnectionFileDescriptor (); - - virtual bool - IsConnected () const; - - virtual lldb::ConnectionStatus - Connect (const char *s, Error *error_ptr); - - virtual lldb::ConnectionStatus - Disconnect (Error *error_ptr); - - virtual size_t - Read (void *dst, - size_t dst_len, - uint32_t timeout_usec, - lldb::ConnectionStatus &status, - Error *error_ptr); - - virtual size_t - Write (const void *src, - size_t src_len, - lldb::ConnectionStatus &status, - Error *error_ptr); - - lldb::ConnectionStatus - BytesAvailable (uint32_t timeout_usec, Error *error_ptr); - - bool - InterruptRead (); - - lldb::IOObjectSP GetReadObject() { return m_read_sp; } - const lldb::IOObjectSP GetReadObject() const { return m_read_sp; } - - uint16_t GetListeningPort(uint32_t timeout_sec); - -protected: - - void - OpenCommandPipe (); - - void - CloseCommandPipe (); - - lldb::ConnectionStatus - SocketListen (const char *host_and_port, Error *error_ptr); - - lldb::ConnectionStatus - ConnectTCP (const char *host_and_port, Error *error_ptr); - - lldb::ConnectionStatus - ConnectUDP (const char *args, Error *error_ptr); - - lldb::ConnectionStatus - NamedSocketConnect (const char *socket_name, Error *error_ptr); - - lldb::ConnectionStatus - NamedSocketAccept (const char *socket_name, Error *error_ptr); - - lldb::IOObjectSP m_read_sp; - lldb::IOObjectSP m_write_sp; - - Predicate m_port_predicate; // Used when binding to port zero to wait for the thread - // that creates the socket, binds and listens to resolve - // the port number. - - Pipe m_pipe; - Mutex m_mutex; - bool m_shutting_down; // This marks that we are shutting down so if we get woken up from - // BytesAvailable to disconnect, we won't try to read again. - bool m_waiting_for_accept; -private: - DISALLOW_COPY_AND_ASSIGN (ConnectionFileDescriptor); -}; - -} // namespace lldb_private - -#endif // liblldb_ConnectionFileDescriptor_h_ diff --git a/include/lldb/Core/DataBuffer.h b/include/lldb/Core/DataBuffer.h index 64e2a8857837..da4934457233 100644 --- a/include/lldb/Core/DataBuffer.h +++ b/include/lldb/Core/DataBuffer.h @@ -14,6 +14,8 @@ #include #include +#include "lldb/lldb-types.h" + namespace lldb_private { //---------------------------------------------------------------------- diff --git a/include/lldb/Core/DataExtractor.h b/include/lldb/Core/DataExtractor.h index c9db2dab73d2..516953b00c33 100644 --- a/include/lldb/Core/DataExtractor.h +++ b/include/lldb/Core/DataExtractor.h @@ -13,9 +13,13 @@ #include "lldb/lldb-private.h" + +#include "llvm/ADT/SmallVector.h" + #include #include #include +#include namespace lldb_private { @@ -85,8 +89,11 @@ public: /// /// @param[in] addr_size /// A new address byte size value. + /// + /// @param[in] target_byte_size + /// A size of a target byte in 8-bit host bytes //------------------------------------------------------------------ - DataExtractor (const void* data, lldb::offset_t data_length, lldb::ByteOrder byte_order, uint32_t addr_size); + DataExtractor (const void* data, lldb::offset_t data_length, lldb::ByteOrder byte_order, uint32_t addr_size, uint32_t target_byte_size = 1); //------------------------------------------------------------------ /// Construct with shared data. @@ -104,8 +111,11 @@ public: /// /// @param[in] addr_size /// A new address byte size value. + /// + /// @param[in] target_byte_size + /// A size of a target byte in 8-bit host bytes //------------------------------------------------------------------ - DataExtractor (const lldb::DataBufferSP& data_sp, lldb::ByteOrder byte_order, uint32_t addr_size); + DataExtractor (const lldb::DataBufferSP& data_sp, lldb::ByteOrder byte_order, uint32_t addr_size, uint32_t target_byte_size = 1); //------------------------------------------------------------------ /// Construct with a subset of \a data. @@ -129,8 +139,11 @@ public: /// /// @param[in] length /// The length in bytes of the subset of data. + /// + /// @param[in] target_byte_size + /// A size of a target byte in 8-bit host bytes //------------------------------------------------------------------ - DataExtractor (const DataExtractor& data, lldb::offset_t offset, lldb::offset_t length); + DataExtractor (const DataExtractor& data, lldb::offset_t offset, lldb::offset_t length, uint32_t target_byte_size = 1); DataExtractor (const DataExtractor& rhs); //------------------------------------------------------------------ @@ -863,7 +876,7 @@ public: *offset_ptr += 1; return val; } - + uint16_t GetU16_unchecked (lldb::offset_t *offset_ptr) const; @@ -1300,6 +1313,11 @@ public: return size - offset; return 0; } + + void + Checksum (llvm::SmallVectorImpl &dest, + uint64_t max_data = 0); + protected: @@ -1311,6 +1329,7 @@ protected: lldb::ByteOrder m_byte_order; ///< The byte order of the data we are extracting from. uint32_t m_addr_size; ///< The address size to use when extracting pointers or addresses mutable lldb::DataBufferSP m_data_sp; ///< The shared pointer to data that can be shared among multilple instances + const uint32_t m_target_byte_size; }; } // namespace lldb_private diff --git a/include/lldb/Core/Debugger.h b/include/lldb/Core/Debugger.h index 7ab62e5b7f3a..15c832f4bf66 100644 --- a/include/lldb/Core/Debugger.h +++ b/include/lldb/Core/Debugger.h @@ -25,6 +25,7 @@ #include "lldb/Core/UserID.h" #include "lldb/Core/UserSettingsController.h" #include "lldb/DataFormatters/FormatManager.h" +#include "lldb/Host/HostThread.h" #include "lldb/Host/Terminal.h" #include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Target/ExecutionContext.h" @@ -249,6 +250,13 @@ public: Stream &s, ValueObject* valobj = NULL); + static bool + FormatDisassemblerAddress (const char *format, + const SymbolContext *sc, + const SymbolContext *prev_sc, + const ExecutionContext *exe_ctx, + const Address *addr, + Stream &s); void ClearIOHandlers (); @@ -287,10 +295,13 @@ public: bool GetAutoConfirm () const; - + + const char * + GetDisassemblyFormat() const; + const char * GetFrameFormat() const; - + const char * GetThreadFormat() const; @@ -336,6 +347,9 @@ public: bool GetAutoOneLineSummaries () const; + bool + GetEscapeNonPrintables () const; + bool GetNotifyVoid () const; @@ -364,9 +378,14 @@ public: bool IsHandlingEvents () const { - return IS_VALID_LLDB_HOST_THREAD(m_event_handler_thread); + return m_event_handler_thread.IsJoinable(); } + // This is for use in the command interpreter, when you either want the selected target, or if no target + // is present you want to prime the dummy target with entities that will be copied over to new targets. + Target *GetSelectedOrDummyTarget(bool prefer_dummy = false); + Target *GetDummyTarget(); + protected: friend class CommandInterpreter; @@ -412,11 +431,16 @@ protected: { return m_source_file_cache; } + + void + InstanceInitialize (); + lldb::StreamFileSP m_input_file_sp; lldb::StreamFileSP m_output_file_sp; lldb::StreamFileSP m_error_file_sp; TerminalState m_terminal_state; TargetList m_target_list; + PlatformList m_platform_list; Listener m_listener; std::unique_ptr m_source_manager_ap; // This is a scratch source manager that we return if we have no targets. @@ -432,12 +456,19 @@ protected: static LoadPluginCallbackType g_load_plugin_callback; typedef std::vector LoadedPluginsList; LoadedPluginsList m_loaded_plugins; - lldb::thread_t m_event_handler_thread; - lldb::thread_t m_io_handler_thread; + HostThread m_event_handler_thread; + HostThread m_io_handler_thread; + Broadcaster m_sync_broadcaster; lldb::ListenerSP m_forward_listener_sp; - void - InstanceInitialize (); - + + //---------------------------------------------------------------------- + // Events for m_sync_broadcaster + //---------------------------------------------------------------------- + enum + { + eBroadcastBitEventThreadIsListening = (1 << 0), + }; + private: // Use Debugger::CreateInstance() to get a shared pointer to a new diff --git a/include/lldb/Core/Disassembler.h b/include/lldb/Core/Disassembler.h index 06a703b4c1aa..b0b841b0a925 100644 --- a/include/lldb/Core/Disassembler.h +++ b/include/lldb/Core/Disassembler.h @@ -77,12 +77,60 @@ public: m_address = addr; } + //------------------------------------------------------------------ + /// Dump the text representation of this Instruction to a Stream + /// + /// Print the (optional) address, (optional) bytes, opcode, + /// operands, and instruction comments to a stream. + /// + /// @param[in] s + /// The Stream to add the text to. + /// + /// @param[in] show_address + /// Whether the address (using disassembly_addr_format_spec formatting) + /// should be printed. + /// + /// @param[in] show_bytes + /// Whether the bytes of the assembly instruction should be printed. + /// + /// @param[in] max_opcode_byte_size + /// The size (in bytes) of the largest instruction in the list that + /// we are printing (for text justification/alignment purposes) + /// Only needed if show_bytes is true. + /// + /// @param[in] exe_ctx + /// The current execution context, if available. May be used in + /// the assembling of the operands+comments for this instruction. + /// Pass NULL if not applicable. + /// + /// @param[in] sym_ctx + /// The SymbolContext for this instruction. + /// Pass NULL if not available/computed. + /// Only needed if show_address is true. + /// + /// @param[in] prev_sym_ctx + /// The SymbolContext for the previous instruction. Depending on + /// the disassembly address format specification, a change in + /// Symbol / Function may mean that a line is printed with the new + /// symbol/function name. + /// Pass NULL if unavailable, or if this is the first instruction of + /// the InstructionList. + /// Only needed if show_address is true. + /// + /// @param[in] disassembly_addr_format_spec + /// The format specification for how addresses are printed. + /// Only needed if show_address is true. + //------------------------------------------------------------------ + virtual void Dump (Stream *s, uint32_t max_opcode_byte_size, bool show_address, bool show_bytes, - const ExecutionContext* exe_ctx); + const ExecutionContext* exe_ctx, + const SymbolContext *sym_ctx, + const SymbolContext *prev_sym_ctx, + const char *disassembly_addr_format_spec); virtual bool DoesBranch () = 0; diff --git a/include/lldb/Core/FileSpecList.h b/include/lldb/Core/FileSpecList.h index f94bdae83c01..7730690ca5b7 100644 --- a/include/lldb/Core/FileSpecList.h +++ b/include/lldb/Core/FileSpecList.h @@ -119,12 +119,15 @@ public: /// @param[in] full /// Should FileSpec::Equal be called with "full" true or false. /// + /// @param[in] remove_backup_dots + /// Should FileSpec::Equal be called with "remove_backup_dots" true or false. + /// /// @return /// The index of the file that matches \a file if it is found, /// else UINT32_MAX is returned. //------------------------------------------------------------------ size_t - FindFileIndex (size_t idx, const FileSpec &file, bool full) const; + FindFileIndex (size_t idx, const FileSpec &file, bool full, bool remove_backup_dots = false) const; //------------------------------------------------------------------ /// Get file at index. diff --git a/include/lldb/Core/IOHandler.h b/include/lldb/Core/IOHandler.h index f477ebd48007..02e6bde1edb6 100644 --- a/include/lldb/Core/IOHandler.h +++ b/include/lldb/Core/IOHandler.h @@ -19,9 +19,11 @@ #include "lldb/Core/ConstString.h" #include "lldb/Core/Error.h" #include "lldb/Core/Flags.h" +#include "lldb/Core/Stream.h" #include "lldb/Core/StringList.h" #include "lldb/Core/ValueObjectList.h" #include "lldb/Host/Mutex.h" +#include "lldb/Host/Predicate.h" namespace curses { @@ -34,9 +36,23 @@ namespace lldb_private { class IOHandler { public: - IOHandler (Debugger &debugger); + enum class Type { + CommandInterpreter, + CommandList, + Confirm, + Curses, + Expression, + ProcessIO, + PythonInterpreter, + PythonCode, + Other + }; + + IOHandler (Debugger &debugger, + IOHandler::Type type); IOHandler (Debugger &debugger, + IOHandler::Type type, const lldb::StreamFileSP &input_sp, const lldb::StreamFileSP &output_sp, const lldb::StreamFileSP &error_sp, @@ -97,6 +113,12 @@ namespace lldb_private { return m_done; } + Type + GetType () const + { + return m_type; + } + virtual void Activate () { @@ -128,7 +150,19 @@ namespace lldb_private { { return ConstString(); } + + virtual const char * + GetCommandPrefix () + { + return NULL; + } + virtual const char * + GetHelpPrologue() + { + return NULL; + } + int GetInputFD(); @@ -206,13 +240,21 @@ namespace lldb_private { //------------------------------------------------------------------ bool GetIsRealTerminal (); - + + void + SetPopped (bool b); + + void + WaitForPop (); + protected: Debugger &m_debugger; lldb::StreamFileSP m_input_sp; lldb::StreamFileSP m_output_sp; lldb::StreamFileSP m_error_sp; + Predicate m_popped; Flags m_flags; + Type m_type; void *m_user_data; bool m_done; bool m_active; @@ -254,7 +296,12 @@ namespace lldb_private { IOHandlerActivated (IOHandler &io_handler) { } - + + virtual void + IOHandlerDeactivated (IOHandler &io_handler) + { + } + virtual int IOHandlerComplete (IOHandler &io_handler, const char *current_line, @@ -264,6 +311,44 @@ namespace lldb_private { int max_matches, StringList &matches); + virtual const char * + IOHandlerGetFixIndentationCharacters () + { + return NULL; + } + + //------------------------------------------------------------------ + /// Called when a new line is created or one of an identifed set of + /// indentation characters is typed. + /// + /// This function determines how much indentation should be added + /// or removed to match the recommended amount for the final line. + /// + /// @param[in] io_handler + /// The IOHandler that responsible for input. + /// + /// @param[in] lines + /// The current input up to the line to be corrected. Lines + /// following the line containing the cursor are not included. + /// + /// @param[in] cursor_position + /// The number of characters preceeding the cursor on the final + /// line at the time. + /// + /// @return + /// Returns an integer describing the number of spaces needed + /// to correct the indentation level. Positive values indicate + /// that spaces should be added, while negative values represent + /// spaces that should be removed. + //------------------------------------------------------------------ + virtual int + IOHandlerFixIndentation (IOHandler &io_handler, + const StringList &lines, + int cursor_position) + { + return 0; + } + //------------------------------------------------------------------ /// Called when a line or lines have been retrieved. /// @@ -275,40 +360,55 @@ namespace lldb_private { //------------------------------------------------------------------ virtual void IOHandlerInputComplete (IOHandler &io_handler, std::string &data) = 0; - + + virtual void + IOHandlerInputInterrupted (IOHandler &io_handler, std::string &data) + { + } + //------------------------------------------------------------------ - /// Called when a line in \a lines has been updated when doing - /// multi-line input. + /// Called to determine whether typing enter after the last line in + /// \a lines should end input. This function will not be called on + /// IOHandler objects that are getting single lines. + /// @param[in] io_handler + /// The IOHandler that responsible for updating the lines. + /// + /// @param[in] lines + /// The current multi-line content. May be altered to provide + /// alternative input when complete. /// /// @return - /// Return an enumeration to indicate the status of the current - /// line: - /// Success - The line is good and should be added to the - /// multiple lines - /// Error - There is an error with the current line and it - /// need to be re-edited before it is acceptable - /// Done - The lines collection is complete and ready to be - /// returned. + /// Return an boolean to indicate whether input is complete, + /// true indicates that no additional input is necessary, while + /// false indicates that more input is required. //------------------------------------------------------------------ - virtual LineStatus - IOHandlerLinesUpdated (IOHandler &io_handler, - StringList &lines, - uint32_t line_idx, - Error &error) + virtual bool + IOHandlerIsInputComplete (IOHandler &io_handler, + StringList &lines) { - return LineStatus::Done; // Stop getting lines on the first line that is updated - // subclasses should do something more intelligent here. - // This function will not be called on IOHandler objects - // that are getting single lines. + // Impose no requirements for input to be considered + // complete. subclasses should do something more intelligent. + return true; } - virtual ConstString IOHandlerGetControlSequence (char ch) { return ConstString(); } + virtual const char * + IOHandlerGetCommandPrefix () + { + return NULL; + } + + virtual const char * + IOHandlerGetHelpPrologue () + { + return NULL; + } + //------------------------------------------------------------------ // Intercept the IOHandler::Interrupt() calls and do something. // @@ -356,30 +456,21 @@ namespace lldb_private { return ConstString(); } - virtual LineStatus - IOHandlerLinesUpdated (IOHandler &io_handler, - StringList &lines, - uint32_t line_idx, - Error &error) + virtual bool + IOHandlerIsInputComplete (IOHandler &io_handler, + StringList &lines) { - if (line_idx == UINT32_MAX) + // Determine whether the end of input signal has been entered + const size_t num_lines = lines.GetSize(); + if (num_lines > 0 && lines[num_lines - 1] == m_end_line) { - // Remove the last empty line from "lines" so it doesn't appear - // in our final expression and return true to indicate we are done + // Remove the terminal line from "lines" so it doesn't appear in + // the resulting input and return true to indicate we are done // getting lines lines.PopBack(); - return LineStatus::Done; - } - else if (line_idx + 1 == lines.GetSize()) - { - // The last line was edited, if this line is empty, then we are done - // getting our multiple lines. - if (lines[line_idx] == m_end_line) - { - return LineStatus::Done; - } + return true; } - return LineStatus::Success; + return false; } protected: const std::string m_end_line; @@ -390,20 +481,26 @@ namespace lldb_private { { public: IOHandlerEditline (Debugger &debugger, + IOHandler::Type type, const char *editline_name, // Used for saving history files const char *prompt, + const char *continuation_prompt, bool multi_line, + bool color_prompts, uint32_t line_number_start, // If non-zero show line numbers starting at 'line_number_start' IOHandlerDelegate &delegate); IOHandlerEditline (Debugger &debugger, + IOHandler::Type type, const lldb::StreamFileSP &input_sp, const lldb::StreamFileSP &output_sp, const lldb::StreamFileSP &error_sp, uint32_t flags, const char *editline_name, // Used for saving history files const char *prompt, + const char *continuation_prompt, bool multi_line, + bool color_prompts, uint32_t line_number_start, // If non-zero show line numbers starting at 'line_number_start' IOHandlerDelegate &delegate); @@ -429,11 +526,10 @@ namespace lldb_private { GotEOF(); virtual void - Activate () - { - IOHandler::Activate(); - m_delegate.IOHandlerActivated(*this); - } + Activate (); + + virtual void + Deactivate (); virtual ConstString GetControlSequence (char ch) @@ -441,12 +537,30 @@ namespace lldb_private { return m_delegate.IOHandlerGetControlSequence (ch); } + virtual const char * + GetCommandPrefix () + { + return m_delegate.IOHandlerGetCommandPrefix (); + } + + virtual const char * + GetHelpPrologue () + { + return m_delegate.IOHandlerGetHelpPrologue (); + } + virtual const char * GetPrompt (); virtual bool SetPrompt (const char *prompt); - + + const char * + GetContinuationPrompt (); + + void + SetContinuationPrompt (const char *prompt); + bool GetLine (std::string &line, bool &interrupted); @@ -456,14 +570,40 @@ namespace lldb_private { void SetBaseLineNumber (uint32_t line); - private: - static LineStatus - LineCompletedCallback (Editline *editline, - StringList &lines, - uint32_t line_idx, - Error &error, - void *baton); + bool + GetInterruptExits () + { + return m_interrupt_exits; + } + void + SetInterruptExits (bool b) + { + m_interrupt_exits = b; + } + + const StringList * + GetCurrentLines () const + { + return m_current_lines_ptr; + } + + uint32_t + GetCurrentLineIndex () const; + + private: +#ifndef LLDB_DISABLE_LIBEDIT + static bool + IsInputCompleteCallback (Editline *editline, + StringList &lines, + void *baton); + + static int + FixIndentationCallback (Editline *editline, + const StringList &lines, + int cursor_position, + void *baton); + static int AutoCompleteCallback (const char *current_line, const char *cursor, const char *last_char, @@ -471,18 +611,28 @@ namespace lldb_private { int max_matches, StringList &matches, void *baton); +#endif protected: +#ifndef LLDB_DISABLE_LIBEDIT std::unique_ptr m_editline_ap; +#endif IOHandlerDelegate &m_delegate; std::string m_prompt; + std::string m_continuation_prompt; + StringList *m_current_lines_ptr; uint32_t m_base_line_number; // If non-zero, then show line numbers in prompt - bool m_multi_line; + uint32_t m_curr_line_idx; + bool m_multi_line; + bool m_color_prompts; + bool m_interrupt_exits; }; + // The order of base classes is important. Look at the constructor of IOHandlerConfirm + // to see how. class IOHandlerConfirm : - public IOHandlerEditline, - public IOHandlerDelegate + public IOHandlerDelegate, + public IOHandlerEditline { public: IOHandlerConfirm (Debugger &debugger, @@ -607,7 +757,8 @@ namespace lldb_private { if (sp) { Mutex::Locker locker (m_mutex); - m_stack.push (sp); + sp->SetPopped (false); + m_stack.push_back (sp); // Set m_top the non-locking IsTop() call m_top = sp.get(); } @@ -627,7 +778,7 @@ namespace lldb_private { { Mutex::Locker locker (m_mutex); if (!m_stack.empty()) - sp = m_stack.top(); + sp = m_stack.back(); } return sp; } @@ -637,12 +788,16 @@ namespace lldb_private { { Mutex::Locker locker (m_mutex); if (!m_stack.empty()) - m_stack.pop(); + { + lldb::IOHandlerSP sp (m_stack.back()); + m_stack.pop_back(); + sp->SetPopped (true); + } // Set m_top the non-locking IsTop() call if (m_stack.empty()) m_top = NULL; else - m_top = m_stack.top().get(); + m_top = m_stack.back().get(); } Mutex & @@ -657,6 +812,19 @@ namespace lldb_private { return m_top == io_handler_sp.get(); } + bool + CheckTopIOHandlerTypes (IOHandler::Type top_type, IOHandler::Type second_top_type) + { + Mutex::Locker locker (m_mutex); + const size_t num_io_handlers = m_stack.size(); + if (num_io_handlers >= 2 && + m_stack[num_io_handlers-1]->GetType() == top_type && + m_stack[num_io_handlers-2]->GetType() == second_top_type) + { + return true; + } + return false; + } ConstString GetTopIOHandlerControlSequence (char ch) { @@ -665,9 +833,26 @@ namespace lldb_private { return ConstString(); } - protected: + const char * + GetTopIOHandlerCommandPrefix() + { + if (m_top) + return m_top->GetCommandPrefix(); + return NULL; + } + + const char * + GetTopIOHandlerHelpPrologue() + { + if (m_top) + return m_top->GetHelpPrologue(); + return NULL; + } + + protected: - std::stack m_stack; + typedef std::vector collection; + collection m_stack; mutable Mutex m_mutex; IOHandler *m_top; diff --git a/include/lldb/Core/Mangled.h b/include/lldb/Core/Mangled.h index 7dc0eca3e8db..2f3df6afd8dc 100644 --- a/include/lldb/Core/Mangled.h +++ b/include/lldb/Core/Mangled.h @@ -37,7 +37,8 @@ public: enum NamePreference { ePreferMangled, - ePreferDemangled + ePreferDemangled, + ePreferDemangledWithoutArguments }; //---------------------------------------------------------------------- diff --git a/include/lldb/Core/ModuleList.h b/include/lldb/Core/ModuleList.h index c3074d4d6510..a46e212da9bb 100644 --- a/include/lldb/Core/ModuleList.h +++ b/include/lldb/Core/ModuleList.h @@ -278,6 +278,16 @@ public: uint32_t name_type_mask, SymbolContextList& sc_list); + //------------------------------------------------------------------ + /// @see Module::FindFunctions () + //------------------------------------------------------------------ + size_t + FindFunctions(const RegularExpression &name, + bool include_symbols, + bool include_inlines, + bool append, + SymbolContextList& sc_list); + //------------------------------------------------------------------ /// Find global and static variables by name. /// @@ -586,6 +596,13 @@ public: return ModuleIterable(m_modules, GetMutex()); } + typedef AdaptedIterable ModuleIterableNoLocking; + ModuleIterableNoLocking + ModulesNoLocking () + { + return ModuleIterableNoLocking(m_modules); + } + }; } // namespace lldb_private diff --git a/include/lldb/Core/PluginManager.h b/include/lldb/Core/PluginManager.h index a2ac67bf9f25..55e6df06d842 100644 --- a/include/lldb/Core/PluginManager.h +++ b/include/lldb/Core/PluginManager.h @@ -342,7 +342,46 @@ public: static UnwindAssemblyCreateInstance GetUnwindAssemblyCreateCallbackForPluginName (const ConstString &name); + + //------------------------------------------------------------------ + // MemoryHistory + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + MemoryHistoryCreateInstance create_callback); + + static bool + UnregisterPlugin (MemoryHistoryCreateInstance create_callback); + + static MemoryHistoryCreateInstance + GetMemoryHistoryCreateCallbackAtIndex (uint32_t idx); + + static MemoryHistoryCreateInstance + GetMemoryHistoryCreateCallbackForPluginName (const ConstString &name); + + //------------------------------------------------------------------ + // InstrumentationRuntime + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + InstrumentationRuntimeCreateInstance create_callback, + InstrumentationRuntimeGetType get_type_callback); + + static bool + UnregisterPlugin (InstrumentationRuntimeCreateInstance create_callback); + static InstrumentationRuntimeGetType + GetInstrumentationRuntimeGetTypeCallbackAtIndex (uint32_t idx); + + static InstrumentationRuntimeCreateInstance + GetInstrumentationRuntimeCreateCallbackAtIndex (uint32_t idx); + + static InstrumentationRuntimeCreateInstance + GetInstrumentationRuntimeCreateCallbackForPluginName (const ConstString &name); + + //------------------------------------------------------------------ // Some plug-ins might register a DebuggerInitializeCallback // callback when registering the plug-in. After a new Debugger diff --git a/include/lldb/Core/RegularExpression.h b/include/lldb/Core/RegularExpression.h index 8e36811fa750..00d8310b4806 100644 --- a/include/lldb/Core/RegularExpression.h +++ b/include/lldb/Core/RegularExpression.h @@ -39,6 +39,9 @@ inline void regfree(llvm_regex_t * a) } #else +#if __ANDROID_NDK__ +#include +#endif #include #endif #include diff --git a/include/lldb/Core/SearchFilter.h b/include/lldb/Core/SearchFilter.h index 57f1b9c1a0a5..bbb7509cedb2 100644 --- a/include/lldb/Core/SearchFilter.h +++ b/include/lldb/Core/SearchFilter.h @@ -225,8 +225,10 @@ public: virtual void Dump (Stream *s) const; -protected: + lldb::SearchFilterSP + CopyForBreakpoint (Breakpoint &breakpoint); +protected: // These are utility functions to assist with the search iteration. They are used by the // default Search method. @@ -248,26 +250,40 @@ protected: const SymbolContext &context, Searcher &searcher); + virtual lldb::SearchFilterSP + DoCopyForBreakpoint (Breakpoint &breakpoint) = 0; + + void + SetTarget(lldb::TargetSP &target_sp) + { + m_target_sp = target_sp; + } + lldb::TargetSP m_target_sp; // Every filter has to be associated with a target for // now since you need a starting place for the search. }; //---------------------------------------------------------------------- -/// @class SearchFilterForNonModuleSpecificSearches SearchFilter.h "lldb/Core/SearchFilter.h" -/// @brief This is a SearchFilter that searches through all modules. It also consults the Target::ModuleIsExcludedForNonModuleSpecificSearches. +/// @class SearchFilterForUnconstrainedSearches SearchFilter.h "lldb/Core/SearchFilter.h" +/// @brief This is a SearchFilter that searches through all modules. It also consults the Target::ModuleIsExcludedForUnconstrainedSearches. //---------------------------------------------------------------------- -class SearchFilterForNonModuleSpecificSearches : +class SearchFilterForUnconstrainedSearches : public SearchFilter { public: - SearchFilterForNonModuleSpecificSearches (const lldb::TargetSP &targetSP) : SearchFilter(targetSP) {} - ~SearchFilterForNonModuleSpecificSearches () {} + SearchFilterForUnconstrainedSearches (const lldb::TargetSP &target_sp) : SearchFilter(target_sp) {} + ~SearchFilterForUnconstrainedSearches () {} - virtual bool - ModulePasses (const FileSpec &module_spec); + bool + ModulePasses (const FileSpec &module_spec) override; - virtual bool - ModulePasses (const lldb::ModuleSP &module_sp); + bool + ModulePasses (const lldb::ModuleSP &module_sp) override; + +protected: + lldb::SearchFilterSP + DoCopyForBreakpoint (Breakpoint &breakpoint) override; + }; //---------------------------------------------------------------------- @@ -301,32 +317,36 @@ public: const SearchFilterByModule& operator=(const SearchFilterByModule& rhs); - virtual bool - ModulePasses (const lldb::ModuleSP &module_sp); + bool + ModulePasses (const lldb::ModuleSP &module_sp) override; - virtual bool - ModulePasses (const FileSpec &spec); + bool + ModulePasses (const FileSpec &spec) override; - virtual bool - AddressPasses (Address &address); + bool + AddressPasses (Address &address) override; - virtual bool - CompUnitPasses (FileSpec &fileSpec); + bool + CompUnitPasses (FileSpec &fileSpec) override; - virtual bool - CompUnitPasses (CompileUnit &compUnit); + bool + CompUnitPasses (CompileUnit &compUnit) override; - virtual void - GetDescription(Stream *s); + void + GetDescription(Stream *s) override; - virtual uint32_t - GetFilterRequiredItems (); + uint32_t + GetFilterRequiredItems () override; - virtual void - Dump (Stream *s) const; + void + Dump (Stream *s) const override; - virtual void - Search (Searcher &searcher); + void + Search (Searcher &searcher) override; + +protected: + lldb::SearchFilterSP + DoCopyForBreakpoint (Breakpoint &breakpoint) override; private: FileSpec m_module_spec; @@ -358,32 +378,36 @@ public: const SearchFilterByModuleList& operator=(const SearchFilterByModuleList& rhs); - virtual bool - ModulePasses (const lldb::ModuleSP &module_sp); + bool + ModulePasses (const lldb::ModuleSP &module_sp) override; - virtual bool - ModulePasses (const FileSpec &spec); + bool + ModulePasses (const FileSpec &spec) override; - virtual bool - AddressPasses (Address &address); + bool + AddressPasses (Address &address) override; - virtual bool - CompUnitPasses (FileSpec &fileSpec); + bool + CompUnitPasses (FileSpec &fileSpec) override; - virtual bool - CompUnitPasses (CompileUnit &compUnit); + bool + CompUnitPasses (CompileUnit &compUnit) override; - virtual void - GetDescription(Stream *s); + void + GetDescription(Stream *s) override; - virtual uint32_t - GetFilterRequiredItems (); + uint32_t + GetFilterRequiredItems () override; - virtual void - Dump (Stream *s) const; + void + Dump (Stream *s) const override; - virtual void - Search (Searcher &searcher); + void + Search (Searcher &searcher) override; + +protected: + lldb::SearchFilterSP + DoCopyForBreakpoint (Breakpoint &breakpoint) override; private: FileSpecList m_module_spec_list; @@ -416,26 +440,30 @@ public: const SearchFilterByModuleListAndCU& operator=(const SearchFilterByModuleListAndCU& rhs); - virtual bool - AddressPasses (Address &address); + bool + AddressPasses (Address &address) override; - virtual bool - CompUnitPasses (FileSpec &fileSpec); + bool + CompUnitPasses (FileSpec &fileSpec) override; - virtual bool - CompUnitPasses (CompileUnit &compUnit); + bool + CompUnitPasses (CompileUnit &compUnit) override; - virtual void - GetDescription(Stream *s); + void + GetDescription(Stream *s) override; - virtual uint32_t - GetFilterRequiredItems (); + uint32_t + GetFilterRequiredItems () override; - virtual void - Dump (Stream *s) const; + void + Dump (Stream *s) const override; - virtual void - Search (Searcher &searcher); + void + Search (Searcher &searcher) override; + +protected: + lldb::SearchFilterSP + DoCopyForBreakpoint (Breakpoint &breakpoint) override; private: FileSpecList m_module_spec_list; diff --git a/include/lldb/Core/Section.h b/include/lldb/Core/Section.h index 32dac5f35b84..65d408e29867 100644 --- a/include/lldb/Core/Section.h +++ b/include/lldb/Core/Section.h @@ -120,7 +120,8 @@ public: lldb::offset_t file_offset, lldb::offset_t file_size, uint32_t log2align, - uint32_t flags); + uint32_t flags, + uint32_t target_byte_size = 1); // Create a section that is a child of parent_section_sp Section (const lldb::SectionSP &parent_section_sp, // NULL for top level sections, non-NULL for child sections @@ -134,7 +135,8 @@ public: lldb::offset_t file_offset, lldb::offset_t file_size, uint32_t log2align, - uint32_t flags); + uint32_t flags, + uint32_t target_byte_size = 1); ~Section (); @@ -297,6 +299,12 @@ public: m_log2align = align; } + // Get the number of host bytes required to hold a target byte + uint32_t + GetTargetByteSize() const + { + return m_target_byte_size; + } protected: @@ -317,6 +325,8 @@ protected: // hits unless the children contain the address. m_encrypted:1, // Set to true if the contents are encrypted m_thread_specific:1;// This section is thread specific + uint32_t m_target_byte_size; // Some architectures have non-8-bit byte size. This is specified as + // as a multiple number of a host bytes private: DISALLOW_COPY_AND_ASSIGN (Section); }; diff --git a/include/lldb/Core/StreamString.h b/include/lldb/Core/StreamString.h index a26ad2d16a05..1aa46dd80a68 100644 --- a/include/lldb/Core/StreamString.h +++ b/include/lldb/Core/StreamString.h @@ -46,6 +46,9 @@ public: size_t GetSize() const; + size_t + GetSizeOfLastLine () const; + std::string & GetString(); diff --git a/include/lldb/Core/ThreadSafeDenseMap.h b/include/lldb/Core/ThreadSafeDenseMap.h new file mode 100644 index 000000000000..f5a7ccfb2ffa --- /dev/null +++ b/include/lldb/Core/ThreadSafeDenseMap.h @@ -0,0 +1,65 @@ +//===-- ThreadSafeDenseMap.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ThreadSafeDenseMap_h_ +#define liblldb_ThreadSafeDenseMap_h_ + +// C Includes +// C++ Includes + +// Other libraries and framework includes +#include "llvm/ADT/DenseMap.h" + +// Project includes +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +template +class ThreadSafeDenseMap +{ +public: + typedef llvm::DenseMap<_KeyType,_ValueType> LLVMMapType; + + ThreadSafeDenseMap(unsigned map_initial_capacity = 0, + Mutex::Type mutex_type = Mutex::eMutexTypeNormal) : + m_map(map_initial_capacity), + m_mutex(mutex_type) + { + } + + void + Insert (_KeyType k, _ValueType v) + { + Mutex::Locker locker(m_mutex); + m_map.insert(std::make_pair(k,v)); + } + + void + Erase (_KeyType k) + { + Mutex::Locker locker(m_mutex); + m_map.erase(k); + } + + _ValueType + Lookup (_KeyType k) + { + Mutex::Locker locker(m_mutex); + return m_map.lookup(k); + } + +protected: + LLVMMapType m_map; + Mutex m_mutex; +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadSafeSTLMap_h_ diff --git a/include/lldb/Core/ThreadSafeSTLMap.h b/include/lldb/Core/ThreadSafeSTLMap.h index 703ce481f637..4235edc92ade 100644 --- a/include/lldb/Core/ThreadSafeSTLMap.h +++ b/include/lldb/Core/ThreadSafeSTLMap.h @@ -16,6 +16,7 @@ // Other libraries and framework includes // Project includes +#include "lldb/lldb-defines.h" #include "lldb/Host/Mutex.h" namespace lldb_private { diff --git a/include/lldb/Core/ValueObject.h b/include/lldb/Core/ValueObject.h index 6a08ec6507f9..fa96c8989913 100644 --- a/include/lldb/Core/ValueObject.h +++ b/include/lldb/Core/ValueObject.h @@ -14,9 +14,11 @@ // C++ Includes #include #include + // Other libraries and framework includes -// Project includes +#include "llvm/ADT/SmallVector.h" +// Project includes #include "lldb/lldb-private.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" @@ -88,6 +90,7 @@ public: { eExpressionPathScanEndReasonEndOfString = 1, // out of data to parse eExpressionPathScanEndReasonNoSuchChild, // child element not found + eExpressionPathScanEndReasonNoSuchSyntheticChild, // (synthetic) child element not found eExpressionPathScanEndReasonEmptyRangeNotAllowed, // [] only allowed for arrays eExpressionPathScanEndReasonDotInsteadOfArrow, // . used when -> should be used eExpressionPathScanEndReasonArrowInsteadOfDot, // -> used when . should be used @@ -129,6 +132,7 @@ public: eClearUserVisibleDataItemsLocation = 1u << 3, eClearUserVisibleDataItemsDescription = 1u << 4, eClearUserVisibleDataItemsSyntheticChildren = 1u << 5, + eClearUserVisibleDataItemsValidator = 1u << 6, eClearUserVisibleDataItemsAllStrings = eClearUserVisibleDataItemsValue | eClearUserVisibleDataItemsSummary | eClearUserVisibleDataItemsLocation | eClearUserVisibleDataItemsDescription, eClearUserVisibleDataItemsAll = 0xFFFF }; @@ -268,12 +272,6 @@ public: m_mod_id = new_id; } - bool - IsFirstEvaluation () const - { - return m_first_update; - } - void SetNeedsUpdate () { @@ -322,7 +320,6 @@ public: ProcessModID m_mod_id; // This is the stop id when this ValueObject was last evaluated. ExecutionContextRef m_exe_ctx_ref; bool m_needs_update; - bool m_first_update; }; const EvaluationPoint & @@ -378,6 +375,9 @@ public: // this vends a TypeImpl that is useful at the SB API layer virtual TypeImpl GetTypeImpl (); + + virtual bool + CanProvideValue (); //------------------------------------------------------------------ // Subclasses must implement the functions below. @@ -607,6 +607,18 @@ public: GetSummaryAsCString (TypeSummaryImpl* summary_ptr, std::string& destination); + bool + GetSummaryAsCString (std::string& destination, + const TypeSummaryOptions& options); + + bool + GetSummaryAsCString (TypeSummaryImpl* summary_ptr, + std::string& destination, + const TypeSummaryOptions& options); + + std::pair + GetValidationStatus (); + const char * GetObjectDescription (); @@ -700,6 +712,10 @@ public: virtual bool IsSynthetic() { return false; } + lldb::ValueObjectSP + GetQualifiedRepresentationIfAvailable (lldb::DynamicValueType dynValue, + bool synthValue); + virtual lldb::ValueObjectSP CreateConstantValue (const ConstString &name); @@ -752,6 +768,18 @@ public: return false; } + virtual bool + DoesProvideSyntheticValue () + { + return false; + } + + bool + IsSyntheticChildrenGenerated (); + + void + SetSyntheticChildrenGenerated (bool b); + virtual SymbolContextScope * GetSymbolContextScope(); @@ -767,12 +795,18 @@ public: const char* expression, const ExecutionContext& exe_ctx); + static lldb::ValueObjectSP + CreateValueObjectFromExpression (const char* name, + const char* expression, + const ExecutionContext& exe_ctx, + const EvaluateExpressionOptions& options); + static lldb::ValueObjectSP CreateValueObjectFromAddress (const char* name, uint64_t address, const ExecutionContext& exe_ctx, ClangASTType type); - + static lldb::ValueObjectSP CreateValueObjectFromData (const char* name, const DataExtractor& data, @@ -787,6 +821,9 @@ public: const DumpValueObjectOptions& options); + lldb::ValueObjectSP + Persist (); + // returns true if this is a char* or a char[] // if it is a char* and check_pointer is true, // it also checks that the pointer is valid @@ -794,7 +831,7 @@ public: IsCStringContainer (bool check_pointer = false); size_t - ReadPointedString (Stream& s, + ReadPointedString (lldb::DataBufferSP& buffer_sp, Error& error, uint32_t max_length = 0, bool honor_array = true, @@ -834,6 +871,10 @@ public: m_format = format; } + + virtual lldb::LanguageType + GetPreferredDisplayLanguage (); + lldb::TypeSummaryImplSP GetSummaryFormat() { @@ -848,6 +889,20 @@ public: ClearUserVisibleData(eClearUserVisibleDataItemsSummary); } + lldb::TypeValidatorImplSP + GetValidator() + { + UpdateFormatsIfNeeded(); + return m_type_validator_sp; + } + + void + SetValidator(lldb::TypeValidatorImplSP format) + { + m_type_validator_sp = format; + ClearUserVisibleData(eClearUserVisibleDataItemsValidator); + } + void SetValueFormat(lldb::TypeFormatImplSP format) { @@ -1018,7 +1073,9 @@ protected: std::string m_summary_str; // Cached summary string that will get cleared if/when the value is updated. std::string m_object_desc_str; // Cached result of the "object printer". This differs from the summary // in that the summary is consed up by us, the object_desc_string is builtin. - + + llvm::Optional> m_validation_result; + ClangASTType m_override_type;// If the type of the value object should be overridden, the type to impose. ValueObjectManager *m_manager; // This object is managed by the root object (any ValueObject that gets created @@ -1043,9 +1100,12 @@ protected: lldb::TypeSummaryImplSP m_type_summary_sp; lldb::TypeFormatImplSP m_type_format_sp; lldb::SyntheticChildrenSP m_synthetic_children_sp; + lldb::TypeValidatorImplSP m_type_validator_sp; ProcessModID m_user_id_of_forced_summary; AddressType m_address_type_of_ptr_or_ref_children; + llvm::SmallVector m_value_checksum; + bool m_value_is_valid:1, m_value_did_change:1, m_children_count_valid:1, @@ -1055,7 +1115,8 @@ protected: m_is_bitfield_for_scalar:1, m_is_child_at_offset:1, m_is_getting_summary:1, - m_did_calculate_complete_objc_class_type:1; + m_did_calculate_complete_objc_class_type:1, + m_is_synthetic_children_generated:1; friend class ClangExpressionDeclMap; // For GetValue friend class ClangExpressionVariable; // For SetName @@ -1150,6 +1211,9 @@ protected: GetLocationAsCStringImpl (const Value& value, const DataExtractor& data); + bool + IsChecksumEmpty (); + private: //------------------------------------------------------------------ // For ValueObject only diff --git a/include/lldb/Core/ValueObjectChild.h b/include/lldb/Core/ValueObjectChild.h index 07d1f294bd80..7bbfe8a662d1 100644 --- a/include/lldb/Core/ValueObjectChild.h +++ b/include/lldb/Core/ValueObjectChild.h @@ -106,6 +106,7 @@ protected: protected: friend class ValueObject; friend class ValueObjectConstResult; + friend class ValueObjectConstResultImpl; ValueObjectChild (ValueObject &parent, const ClangASTType &clang_type, const ConstString &name, diff --git a/include/lldb/Core/ValueObjectConstResult.h b/include/lldb/Core/ValueObjectConstResult.h index dd87fc848ae8..4e05d50132ec 100644 --- a/include/lldb/Core/ValueObjectConstResult.h +++ b/include/lldb/Core/ValueObjectConstResult.h @@ -59,7 +59,8 @@ public: static lldb::ValueObjectSP Create (ExecutionContextScope *exe_scope, Value &value, - const ConstString &name); + const ConstString &name, + Module* module = nullptr); // When an expression fails to evaluate, we return an error static lldb::ValueObjectSP @@ -126,6 +127,9 @@ public: virtual lldb::ValueObjectSP GetDynamicValue (lldb::DynamicValueType valueType); + + virtual lldb::LanguageType + GetPreferredDisplayLanguage (); protected: virtual bool @@ -169,7 +173,8 @@ private: ValueObjectConstResult (ExecutionContextScope *exe_scope, const Value &value, - const ConstString &name); + const ConstString &name, + Module* module = nullptr); ValueObjectConstResult (ExecutionContextScope *exe_scope, const Error& error); diff --git a/include/lldb/Core/ValueObjectConstResultImpl.h b/include/lldb/Core/ValueObjectConstResultImpl.h index 271b93823569..e3574e8a4d4e 100644 --- a/include/lldb/Core/ValueObjectConstResultImpl.h +++ b/include/lldb/Core/ValueObjectConstResultImpl.h @@ -47,13 +47,6 @@ public: lldb::ValueObjectSP AddressOf (Error &error); - bool - NeedsDerefOnTarget() - { - m_impl_backend->UpdateValueIfNeeded(false); - return (m_impl_backend->GetValue().GetValueType() == Value::eValueTypeHostAddress); - } - lldb::addr_t GetLiveAddress() { @@ -68,9 +61,6 @@ public: m_live_address_type = address_type; } - lldb::ValueObjectSP - DerefOnTarget(); - virtual lldb::addr_t GetAddressOf (bool scalar_is_load_address = true, AddressType *address_type = NULL); diff --git a/include/lldb/Core/ValueObjectSyntheticFilter.h b/include/lldb/Core/ValueObjectSyntheticFilter.h index e12698f49bb1..49c5601dc0e5 100644 --- a/include/lldb/Core/ValueObjectSyntheticFilter.h +++ b/include/lldb/Core/ValueObjectSyntheticFilter.h @@ -12,10 +12,10 @@ // C Includes // C++ Includes -#include #include // Other libraries and framework includes // Project includes +#include "lldb/Core/ThreadSafeSTLMap.h" #include "lldb/Core/ValueObject.h" namespace lldb_private { @@ -132,11 +132,12 @@ public: GetNonSyntheticValue (); virtual bool - ResolveValue (Scalar &scalar) + CanProvideValue (); + + virtual bool + DoesProvideSyntheticValue () { - if (m_parent) - return m_parent->ResolveValue(scalar); - return false; + return (UpdateValueIfNeeded(), m_provides_value == eLazyBoolYes); } protected: @@ -153,8 +154,8 @@ protected: lldb::SyntheticChildrenSP m_synth_sp; std::unique_ptr m_synth_filter_ap; - typedef std::map ByIndexMap; - typedef std::map NameToIndexMap; + typedef ThreadSafeSTLMap ByIndexMap; + typedef ThreadSafeSTLMap NameToIndexMap; typedef ByIndexMap::iterator ByIndexIterator; typedef NameToIndexMap::iterator NameToIndexIterator; @@ -167,12 +168,14 @@ protected: LazyBool m_might_have_children; + LazyBool m_provides_value; + private: friend class ValueObject; ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter); void - CopyParentData (); + CopyValueData (ValueObject *source); //------------------------------------------------------------------ // For ValueObject only diff --git a/include/lldb/DataFormatters/CXXFormatterFunctions.h b/include/lldb/DataFormatters/CXXFormatterFunctions.h index 753ffa1bae1b..53b7468bb13c 100644 --- a/include/lldb/DataFormatters/CXXFormatterFunctions.h +++ b/include/lldb/DataFormatters/CXXFormatterFunctions.h @@ -61,419 +61,139 @@ namespace lldb_private { GetOSXEpoch (); bool - Char16StringSummaryProvider (ValueObject& valobj, Stream& stream); // char16_t* and unichar* + FunctionPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // C++ function pointer bool - Char32StringSummaryProvider (ValueObject& valobj, Stream& stream); // char32_t* + Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char16_t* and unichar* bool - WCharStringSummaryProvider (ValueObject& valobj, Stream& stream); // wchar_t* + Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char32_t* bool - Char16SummaryProvider (ValueObject& valobj, Stream& stream); // char16_t and unichar + WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // wchar_t* bool - Char32SummaryProvider (ValueObject& valobj, Stream& stream); // char32_t + Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char16_t and unichar bool - WCharSummaryProvider (ValueObject& valobj, Stream& stream); // wchar_t + Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char32_t bool - LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream); // libc++ std::string + WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // wchar_t + + bool + LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::string bool - LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream); // libc++ std::wstring + LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::wstring bool - LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream); // libc++ std::shared_ptr<> and std::weak_ptr<> + LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::shared_ptr<> and std::weak_ptr<> bool - ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream); + ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); SyntheticChildrenFrontEnd* ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); template bool - NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream); + NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream); + NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - NSArraySummaryProvider (ValueObject& valobj, Stream& stream); + NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); template bool - NSSetSummaryProvider (ValueObject& valobj, Stream& stream); + NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); template bool - NSDataSummaryProvider (ValueObject& valobj, Stream& stream); + NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - NSNumberSummaryProvider (ValueObject& valobj, Stream& stream); + NSNumberSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream); + NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream); + NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream); + NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - CFBagSummaryProvider (ValueObject& valobj, Stream& stream); + CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream); + CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream); + CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - NSDateSummaryProvider (ValueObject& valobj, Stream& stream); + NSDateSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream); + CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - NSBundleSummaryProvider (ValueObject& valobj, Stream& stream); + NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - NSStringSummaryProvider (ValueObject& valobj, Stream& stream); + NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream); bool - NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream); + NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream); + NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - NSURLSummaryProvider (ValueObject& valobj, Stream& stream); + NSURLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream); + ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); template bool - ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream); + ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); bool - RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream); + RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); extern template bool - NSDictionarySummaryProvider (ValueObject&, Stream&) ; + NSDictionarySummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; extern template bool - NSDictionarySummaryProvider (ValueObject&, Stream&) ; + NSDictionarySummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; extern template bool - NSDataSummaryProvider (ValueObject&, Stream&) ; + NSDataSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; extern template bool - NSDataSummaryProvider (ValueObject&, Stream&) ; + NSDataSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; extern template bool - ObjCSELSummaryProvider (ValueObject&, Stream&); + ObjCSELSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&); extern template bool - ObjCSELSummaryProvider (ValueObject&, Stream&); + ObjCSELSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&); SyntheticChildrenFrontEnd* NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - class NSDictionaryISyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - private: - struct DataDescriptor_32 - { - uint32_t _used : 26; - uint32_t _szidx : 6; - }; - struct DataDescriptor_64 - { - uint64_t _used : 58; - uint32_t _szidx : 6; - }; - - struct DictionaryItemDescriptor - { - lldb::addr_t key_ptr; - lldb::addr_t val_ptr; - lldb::ValueObjectSP valobj_sp; - }; - - public: - NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSDictionaryISyntheticFrontEnd (); - private: - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - lldb::ByteOrder m_order; - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; - lldb::addr_t m_data_ptr; - ClangASTType m_pair_type; - std::vector m_children; - }; - - class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - private: - struct DataDescriptor_32 - { - uint32_t _used : 26; - uint32_t _kvo : 1; - uint32_t _size; - uint32_t _mutations; - uint32_t _objs_addr; - uint32_t _keys_addr; - }; - struct DataDescriptor_64 - { - uint64_t _used : 58; - uint32_t _kvo : 1; - uint64_t _size; - uint64_t _mutations; - uint64_t _objs_addr; - uint64_t _keys_addr; - }; - struct DictionaryItemDescriptor - { - lldb::addr_t key_ptr; - lldb::addr_t val_ptr; - lldb::ValueObjectSP valobj_sp; - }; - public: - NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSDictionaryMSyntheticFrontEnd (); - private: - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - lldb::ByteOrder m_order; - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; - ClangASTType m_pair_type; - std::vector m_children; - }; - - class NSDictionaryCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSDictionaryCodeRunningSyntheticFrontEnd (); - }; - SyntheticChildrenFrontEnd* NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - class NSSetISyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - private: - struct DataDescriptor_32 - { - uint32_t _used : 26; - uint32_t _szidx : 6; - }; - struct DataDescriptor_64 - { - uint64_t _used : 58; - uint32_t _szidx : 6; - }; - - struct SetItemDescriptor - { - lldb::addr_t item_ptr; - lldb::ValueObjectSP valobj_sp; - }; - - public: - NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSSetISyntheticFrontEnd (); - private: - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; - lldb::addr_t m_data_ptr; - std::vector m_children; - }; - - class NSOrderedSetSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - private: - - public: - NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSOrderedSetSyntheticFrontEnd (); - private: - uint32_t m_count; - std::map m_children; - }; - - class NSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - private: - struct DataDescriptor_32 - { - uint32_t _used : 26; - uint32_t _size; - uint32_t _mutations; - uint32_t _objs_addr; - }; - struct DataDescriptor_64 - { - uint64_t _used : 58; - uint64_t _size; - uint64_t _mutations; - uint64_t _objs_addr; - }; - struct SetItemDescriptor - { - lldb::addr_t item_ptr; - lldb::ValueObjectSP valobj_sp; - }; - public: - NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSSetMSyntheticFrontEnd (); - private: - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; - std::vector m_children; - }; - - class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - NSSetCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSSetCodeRunningSyntheticFrontEnd (); - }; - SyntheticChildrenFrontEnd* NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + class LibcxxVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: @@ -507,7 +227,7 @@ namespace lldb_private { SyntheticChildrenFrontEnd* LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); bool - LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream); + LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); class LibstdcppVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd { @@ -665,148 +385,16 @@ namespace lldb_private { SyntheticChildrenFrontEnd* LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - class LibcxxStdVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~LibcxxStdVectorSyntheticFrontEnd (); - private: - ValueObject* m_start; - ValueObject* m_finish; - ClangASTType m_element_type; - uint32_t m_element_size; - std::map m_children; - }; - SyntheticChildrenFrontEnd* LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - class LibcxxStdListSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~LibcxxStdListSyntheticFrontEnd (); - private: - bool - HasLoop(); - - size_t m_list_capping_size; - static const bool g_use_loop_detect = true; - lldb::addr_t m_node_address; - ValueObject* m_head; - ValueObject* m_tail; - ClangASTType m_element_type; - size_t m_count; - std::map m_children; - }; - SyntheticChildrenFrontEnd* LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~LibcxxStdMapSyntheticFrontEnd (); - private: - bool - GetDataType(); - - void - GetValueOffset (const lldb::ValueObjectSP& node); - - ValueObject* m_tree; - ValueObject* m_root_node; - ClangASTType m_element_type; - uint32_t m_skip_size; - size_t m_count; - std::map m_children; - }; - SyntheticChildrenFrontEnd* LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - class LibcxxStdUnorderedMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~LibcxxStdUnorderedMapSyntheticFrontEnd (); - private: - - ValueObject* m_tree; - size_t m_num_elements; - ValueObject* m_next_element; - std::map m_children; - std::vector > m_elements_cache; - }; - SyntheticChildrenFrontEnd* LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + SyntheticChildrenFrontEnd* LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + } // namespace formatters } // namespace lldb_private diff --git a/include/lldb/DataFormatters/DataVisualization.h b/include/lldb/DataFormatters/DataVisualization.h index ca0714c29f84..a0b2e58bba28 100644 --- a/include/lldb/DataFormatters/DataVisualization.h +++ b/include/lldb/DataFormatters/DataVisualization.h @@ -72,6 +72,13 @@ public: lldb::DynamicValueType use_dynamic); #endif + static lldb::TypeValidatorImplSP + GetValidator (ValueObject& valobj, + lldb::DynamicValueType use_dynamic); + + static lldb::TypeValidatorImplSP + GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp); + static bool AnyMatches(ConstString type_name, TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, @@ -136,6 +143,12 @@ public: static void Disable (const lldb::TypeCategoryImplSP& category); + static void + EnableStar (); + + static void + DisableStar (); + static void LoopThrough (FormatManager::CategoryCallback callback, void* callback_baton); diff --git a/include/lldb/DataFormatters/FormatCache.h b/include/lldb/DataFormatters/FormatCache.h index 1505d7c46189..fa46306e5404 100644 --- a/include/lldb/DataFormatters/FormatCache.h +++ b/include/lldb/DataFormatters/FormatCache.h @@ -31,16 +31,19 @@ private: bool m_format_cached : 1; bool m_summary_cached : 1; bool m_synthetic_cached : 1; + bool m_validator_cached : 1; lldb::TypeFormatImplSP m_format_sp; lldb::TypeSummaryImplSP m_summary_sp; lldb::SyntheticChildrenSP m_synthetic_sp; + lldb::TypeValidatorImplSP m_validator_sp; public: Entry (); Entry (lldb::TypeFormatImplSP); Entry (lldb::TypeSummaryImplSP); Entry (lldb::SyntheticChildrenSP); - Entry (lldb::TypeFormatImplSP,lldb::TypeSummaryImplSP,lldb::SyntheticChildrenSP); + Entry (lldb::TypeValidatorImplSP); + Entry (lldb::TypeFormatImplSP,lldb::TypeSummaryImplSP,lldb::SyntheticChildrenSP,lldb::TypeValidatorImplSP); bool IsFormatCached (); @@ -51,6 +54,9 @@ private: bool IsSyntheticCached (); + bool + IsValidatorCached (); + lldb::TypeFormatImplSP GetFormat (); @@ -60,6 +66,9 @@ private: lldb::SyntheticChildrenSP GetSynthetic (); + lldb::TypeValidatorImplSP + GetValidator (); + void SetFormat (lldb::TypeFormatImplSP); @@ -68,6 +77,9 @@ private: void SetSynthetic (lldb::SyntheticChildrenSP); + + void + SetValidator (lldb::TypeValidatorImplSP); }; typedef std::map CacheMap; CacheMap m_map; @@ -91,6 +103,9 @@ public: bool GetSynthetic (const ConstString& type,lldb::SyntheticChildrenSP& synthetic_sp); + bool + GetValidator (const ConstString& type,lldb::TypeValidatorImplSP& summary_sp); + void SetFormat (const ConstString& type,lldb::TypeFormatImplSP& format_sp); @@ -100,6 +115,9 @@ public: void SetSynthetic (const ConstString& type,lldb::SyntheticChildrenSP& synthetic_sp); + void + SetValidator (const ConstString& type,lldb::TypeValidatorImplSP& synthetic_sp); + void Clear (); diff --git a/include/lldb/DataFormatters/FormatManager.h b/include/lldb/DataFormatters/FormatManager.h index 0b9144dffa17..37dae6536761 100644 --- a/include/lldb/DataFormatters/FormatManager.h +++ b/include/lldb/DataFormatters/FormatManager.h @@ -86,6 +86,18 @@ public: m_categories_map.Disable(category); } + void + EnableAllCategories () + { + m_categories_map.EnableAllCategories (); + } + + void + DisableAllCategories () + { + m_categories_map.DisableAllCategories (); + } + bool DeleteCategory (const ConstString& category_name) { @@ -148,6 +160,9 @@ public: GetSyntheticChildrenForType (lldb::TypeNameSpecifierImplSP type_sp); #endif + lldb::TypeValidatorImplSP + GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp); + lldb::TypeFormatImplSP GetFormat (ValueObject& valobj, lldb::DynamicValueType use_dynamic); @@ -162,6 +177,10 @@ public: lldb::DynamicValueType use_dynamic); #endif + lldb::TypeValidatorImplSP + GetValidator (ValueObject& valobj, + lldb::DynamicValueType use_dynamic); + bool AnyMatches (ConstString type_name, TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, @@ -272,6 +291,7 @@ private: HardcodedFormatterFinders m_hardcoded_formats; HardcodedFormatterFinders m_hardcoded_summaries; HardcodedFormatterFinders m_hardcoded_synthetics; + HardcodedFormatterFinders m_hardcoded_validators; lldb::TypeFormatImplSP GetHardcodedFormat (ValueObject&,lldb::DynamicValueType); @@ -282,6 +302,9 @@ private: lldb::SyntheticChildrenSP GetHardcodedSyntheticChildren (ValueObject&,lldb::DynamicValueType); + lldb::TypeValidatorImplSP + GetHardcodedValidator (ValueObject&,lldb::DynamicValueType); + TypeCategoryMap& GetCategories () { diff --git a/include/lldb/DataFormatters/FormattersContainer.h b/include/lldb/DataFormatters/FormattersContainer.h index de838d1ab9c1..daf2f24ae3e5 100644 --- a/include/lldb/DataFormatters/FormattersContainer.h +++ b/include/lldb/DataFormatters/FormattersContainer.h @@ -29,6 +29,7 @@ #include "lldb/DataFormatters/TypeFormat.h" #include "lldb/DataFormatters/TypeSummary.h" #include "lldb/DataFormatters/TypeSynthetic.h" +#include "lldb/DataFormatters/TypeValidator.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangASTType.h" @@ -38,6 +39,8 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/TargetList.h" +#include "lldb/Utility/StringLexer.h" + namespace lldb_private { // this file (and its. cpp) contain the low-level implementation of LLDB Data Visualization @@ -58,18 +61,6 @@ public: }; -static inline bool -IsWhitespace (char c) -{ - return ( (c == ' ') || (c == '\t') || (c == '\v') || (c == '\f') ); -} - -static inline bool -HasPrefix (const char* str1, const char* str2) -{ - return ( ::strstr(str1, str2) == str1 ); -} - // if the user tries to add formatters for, say, "struct Foo" // those will not match any type because of the way we strip qualifiers from typenames // this method looks for the case where the user is adding a "class","struct","enum" or "union" Foo @@ -77,32 +68,23 @@ HasPrefix (const char* str1, const char* str2) static inline ConstString GetValidTypeName_Impl (const ConstString& type) { - int strip_len = 0; - - if ((bool)type == false) + if (type.IsEmpty()) return type; - const char* type_cstr = type.AsCString(); - - if ( HasPrefix(type_cstr, "class ") ) - strip_len = 6; - else if ( HasPrefix(type_cstr, "enum ") ) - strip_len = 5; - else if ( HasPrefix(type_cstr, "struct ") ) - strip_len = 7; - else if ( HasPrefix(type_cstr, "union ") ) - strip_len = 6; + std::string type_cstr(type.AsCString()); + lldb_utility::StringLexer type_lexer(type_cstr); - if (strip_len == 0) - return type; + type_lexer.AdvanceIf("class "); + type_lexer.AdvanceIf("enum "); + type_lexer.AdvanceIf("struct "); + type_lexer.AdvanceIf("union "); - type_cstr += strip_len; - while (IsWhitespace(*type_cstr) && ++type_cstr) + while (type_lexer.NextIf({' ','\t','\v','\f'}).first) ; - return ConstString(type_cstr); + return ConstString(type_lexer.GetUnlexed()); } - + template class FormattersContainer; @@ -267,8 +249,7 @@ public: FormattersContainer(std::string name, IFormatChangeListener* lst) : m_format_map(lst), - m_name(name), - m_id_cs(ConstString("id")) + m_name(name) { } @@ -345,15 +326,11 @@ public: } protected: - BackEndType m_format_map; - std::string m_name; DISALLOW_COPY_AND_ASSIGN(FormattersContainer); - ConstString m_id_cs; - void Add_Impl (const MapKeyType &type, const MapValueType& entry, lldb::RegularExpressionSP *dummy) { diff --git a/include/lldb/DataFormatters/StringPrinter.h b/include/lldb/DataFormatters/StringPrinter.h new file mode 100644 index 000000000000..48e27ace5d92 --- /dev/null +++ b/include/lldb/DataFormatters/StringPrinter.h @@ -0,0 +1,290 @@ +//===-- StringPrinter.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_StringPrinter_h_ +#define liblldb_StringPrinter_h_ + +#include "lldb/lldb-forward.h" + +#include "lldb/Core/DataExtractor.h" + +namespace lldb_private { + namespace formatters + { + + enum class StringElementType { + ASCII, + UTF8, + UTF16, + UTF32 + }; + + class ReadStringAndDumpToStreamOptions + { + public: + + ReadStringAndDumpToStreamOptions () : + m_location(0), + m_process_sp(), + m_stream(NULL), + m_prefix_token(0), + m_quote('"'), + m_source_size(0), + m_needs_zero_termination(true), + m_escape_non_printables(true), + m_ignore_max_length(false) + { + } + + ReadStringAndDumpToStreamOptions (ValueObject& valobj); + + ReadStringAndDumpToStreamOptions& + SetLocation (uint64_t l) + { + m_location = l; + return *this; + } + + uint64_t + GetLocation () const + { + return m_location; + } + + ReadStringAndDumpToStreamOptions& + SetProcessSP (lldb::ProcessSP p) + { + m_process_sp = p; + return *this; + } + + lldb::ProcessSP + GetProcessSP () const + { + return m_process_sp; + } + + ReadStringAndDumpToStreamOptions& + SetStream (Stream* s) + { + m_stream = s; + return *this; + } + + Stream* + GetStream () const + { + return m_stream; + } + + ReadStringAndDumpToStreamOptions& + SetPrefixToken (char p) + { + m_prefix_token = p; + return *this; + } + + char + GetPrefixToken () const + { + return m_prefix_token; + } + + ReadStringAndDumpToStreamOptions& + SetQuote (char q) + { + m_quote = q; + return *this; + } + + char + GetQuote () const + { + return m_quote; + } + + ReadStringAndDumpToStreamOptions& + SetSourceSize (uint32_t s) + { + m_source_size = s; + return *this; + } + + uint32_t + GetSourceSize () const + { + return m_source_size; + } + + ReadStringAndDumpToStreamOptions& + SetNeedsZeroTermination (bool z) + { + m_needs_zero_termination = z; + return *this; + } + + bool + GetNeedsZeroTermination () const + { + return m_needs_zero_termination; + } + + ReadStringAndDumpToStreamOptions& + SetEscapeNonPrintables (bool e) + { + m_escape_non_printables = e; + return *this; + } + + bool + GetEscapeNonPrintables () const + { + return m_escape_non_printables; + } + + ReadStringAndDumpToStreamOptions& + SetIgnoreMaxLength (bool e) + { + m_ignore_max_length = e; + return *this; + } + + bool + GetIgnoreMaxLength () const + { + return m_ignore_max_length; + } + + private: + uint64_t m_location; + lldb::ProcessSP m_process_sp; + Stream* m_stream; + char m_prefix_token; + char m_quote; + uint32_t m_source_size; + bool m_needs_zero_termination; + bool m_escape_non_printables; + bool m_ignore_max_length; + }; + + class ReadBufferAndDumpToStreamOptions + { + public: + + ReadBufferAndDumpToStreamOptions () : + m_data(), + m_stream(NULL), + m_prefix_token(0), + m_quote('"'), + m_source_size(0), + m_escape_non_printables(true) + { + } + + ReadBufferAndDumpToStreamOptions (ValueObject& valobj); + + ReadBufferAndDumpToStreamOptions& + SetData (DataExtractor d) + { + m_data = d; + return *this; + } + + lldb_private::DataExtractor + GetData () const + { + return m_data; + } + + ReadBufferAndDumpToStreamOptions& + SetStream (Stream* s) + { + m_stream = s; + return *this; + } + + Stream* + GetStream () const + { + return m_stream; + } + + ReadBufferAndDumpToStreamOptions& + SetPrefixToken (char p) + { + m_prefix_token = p; + return *this; + } + + char + GetPrefixToken () const + { + return m_prefix_token; + } + + ReadBufferAndDumpToStreamOptions& + SetQuote (char q) + { + m_quote = q; + return *this; + } + + char + GetQuote () const + { + return m_quote; + } + + ReadBufferAndDumpToStreamOptions& + SetSourceSize (uint32_t s) + { + m_source_size = s; + return *this; + } + + uint32_t + GetSourceSize () const + { + return m_source_size; + } + + ReadBufferAndDumpToStreamOptions& + SetEscapeNonPrintables (bool e) + { + m_escape_non_printables = e; + return *this; + } + + bool + GetEscapeNonPrintables () const + { + return m_escape_non_printables; + } + + private: + DataExtractor m_data; + Stream* m_stream; + char m_prefix_token; + char m_quote; + uint32_t m_source_size; + bool m_escape_non_printables; + }; + + template + bool + ReadStringAndDumpToStream (ReadStringAndDumpToStreamOptions options); + + template + bool + ReadBufferAndDumpToStream (ReadBufferAndDumpToStreamOptions options); + + } // namespace formatters +} // namespace lldb_private + +#endif // liblldb_StringPrinter_h_ diff --git a/include/lldb/DataFormatters/TypeCategory.h b/include/lldb/DataFormatters/TypeCategory.h index 491fef29b5c5..e32efa420a55 100644 --- a/include/lldb/DataFormatters/TypeCategory.h +++ b/include/lldb/DataFormatters/TypeCategory.h @@ -71,6 +71,7 @@ namespace lldb_private { typedef FormatterContainerPair FormatContainer; typedef FormatterContainerPair SummaryContainer; typedef FormatterContainerPair FilterContainer; + typedef FormatterContainerPair ValidatorContainer; #ifndef LLDB_DISABLE_PYTHON typedef FormatterContainerPair SynthContainer; @@ -94,6 +95,9 @@ namespace lldb_private { typedef SynthContainer::RegexMatchContainerSP RegexSynthContainerSP; #endif // #ifndef LLDB_DISABLE_PYTHON + typedef ValidatorContainer::ExactMatchContainerSP ValidatorContainerSP; + typedef ValidatorContainer::RegexMatchContainerSP RegexValidatorContainerSP; + TypeCategoryImpl (IFormatChangeListener* clist, ConstString name); @@ -147,6 +151,9 @@ namespace lldb_private { GetSyntheticForType (lldb::TypeNameSpecifierImplSP type_sp); #endif + ValidatorContainer::MapValueType + GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp); + lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierForFormatAtIndex (size_t index); @@ -183,9 +190,26 @@ namespace lldb_private { lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierForSyntheticAtIndex (size_t index); - #endif // #ifndef LLDB_DISABLE_PYTHON + ValidatorContainerSP + GetTypeValidatorsContainer () + { + return m_validator_cont.GetExactMatch(); + } + + RegexValidatorContainerSP + GetRegexTypeValidatorsContainer () + { + return m_validator_cont.GetRegexMatch(); + } + + ValidatorContainer::MapValueType + GetValidatorAtIndex (size_t index); + + lldb::TypeNameSpecifierImplSP + GetTypeNameSpecifierForValidatorAtIndex (size_t index); + bool IsEnabled () const { @@ -219,6 +243,12 @@ namespace lldb_private { lldb::SyntheticChildrenSP& entry, uint32_t* reason = NULL); + bool + Get (ValueObject& valobj, + const FormattersMatchVector& candidates, + lldb::TypeValidatorImplSP& entry, + uint32_t* reason = NULL); + void Clear (FormatCategoryItems items = ALL_ITEM_TYPES); @@ -246,14 +276,12 @@ namespace lldb_private { private: FormatContainer m_format_cont; - SummaryContainer m_summary_cont; - FilterContainer m_filter_cont; - #ifndef LLDB_DISABLE_PYTHON SynthContainer m_synth_cont; #endif // #ifndef LLDB_DISABLE_PYTHON + ValidatorContainer m_validator_cont; bool m_enabled; @@ -274,6 +302,18 @@ namespace lldb_private { Enable(false, UINT32_MAX); } + uint32_t + GetLastEnabledPosition () + { + return m_enabled_position; + } + + void + SetEnabledPosition (uint32_t p) + { + m_enabled_position = p; + } + friend class TypeCategoryMap; friend class FormattersContainer; @@ -289,6 +329,9 @@ namespace lldb_private { friend class FormattersContainer; friend class FormattersContainer; #endif // #ifndef LLDB_DISABLE_PYTHON + + friend class FormattersContainer; + friend class FormattersContainer; }; } // namespace lldb_private diff --git a/include/lldb/DataFormatters/TypeCategoryMap.h b/include/lldb/DataFormatters/TypeCategoryMap.h index 88aaeb23bfd8..41b170d5335e 100644 --- a/include/lldb/DataFormatters/TypeCategoryMap.h +++ b/include/lldb/DataFormatters/TypeCategoryMap.h @@ -63,6 +63,12 @@ namespace lldb_private { bool Disable (ValueSP category); + + void + EnableAllCategories (); + + void + DisableAllCategories (); void Clear (); @@ -108,6 +114,10 @@ namespace lldb_private { lldb::DynamicValueType use_dynamic); #endif + lldb::TypeValidatorImplSP + GetValidator (ValueObject& valobj, + lldb::DynamicValueType use_dynamic); + private: class delete_matching_categories diff --git a/include/lldb/DataFormatters/TypeSummary.h b/include/lldb/DataFormatters/TypeSummary.h index 699494336cc6..2d4e03ad9b5d 100644 --- a/include/lldb/DataFormatters/TypeSummary.h +++ b/include/lldb/DataFormatters/TypeSummary.h @@ -28,6 +28,32 @@ #include "lldb/Symbol/Type.h" namespace lldb_private { + class TypeSummaryOptions + { + public: + TypeSummaryOptions (); + TypeSummaryOptions (const TypeSummaryOptions& rhs); + + TypeSummaryOptions& + operator = (const TypeSummaryOptions& rhs); + + lldb::LanguageType + GetLanguage () const; + + lldb::TypeSummaryCapping + GetCapping () const; + + TypeSummaryOptions& + SetLanguage (lldb::LanguageType); + + TypeSummaryOptions& + SetCapping (lldb::TypeSummaryCapping); + + ~TypeSummaryOptions() = default; + private: + lldb::LanguageType m_lang; + lldb::TypeSummaryCapping m_capping; + }; class TypeSummaryImpl { @@ -313,7 +339,8 @@ namespace lldb_private { // for us to generate its summary virtual bool FormatObject (ValueObject *valobj, - std::string& dest) = 0; + std::string& dest, + const TypeSummaryOptions& options) = 0; virtual std::string GetDescription () = 0; @@ -372,7 +399,8 @@ namespace lldb_private { virtual bool FormatObject(ValueObject *valobj, - std::string& dest); + std::string& dest, + const TypeSummaryOptions& options); virtual std::string GetDescription(); @@ -397,10 +425,11 @@ namespace lldb_private { // summaries implemented via a C++ function struct CXXFunctionSummaryFormat : public TypeSummaryImpl { - // we should convert these to SBValue and SBStream if we ever cross // the boundary towards the external world - typedef bool (*Callback)(ValueObject& valobj, Stream& dest); + typedef bool (*Callback)(ValueObject&, + Stream&, + const TypeSummaryOptions&); Callback m_impl; std::string m_description; @@ -443,7 +472,8 @@ namespace lldb_private { virtual bool FormatObject (ValueObject *valobj, - std::string& dest); + std::string& dest, + const TypeSummaryOptions& options); virtual std::string GetDescription (); @@ -517,7 +547,8 @@ namespace lldb_private { virtual bool FormatObject (ValueObject *valobj, - std::string& dest); + std::string& dest, + const TypeSummaryOptions& options); virtual std::string GetDescription (); diff --git a/include/lldb/DataFormatters/TypeSynthetic.h b/include/lldb/DataFormatters/TypeSynthetic.h index a25f11d64392..675c43b1f311 100644 --- a/include/lldb/DataFormatters/TypeSynthetic.h +++ b/include/lldb/DataFormatters/TypeSynthetic.h @@ -24,8 +24,6 @@ #include "lldb/lldb-enumerations.h" #include "lldb/Core/ValueObject.h" -#include "lldb/Interpreter/ScriptInterpreterPython.h" -#include "lldb/Symbol/Type.h" namespace lldb_private { class SyntheticChildrenFrontEnd @@ -81,14 +79,71 @@ namespace lldb_private { virtual bool MightHaveChildren () = 0; + // if this function returns a non-null ValueObject, then the returned ValueObject will stand + // for this ValueObject whenever a "value" request is made to this ValueObject + virtual lldb::ValueObjectSP + GetSyntheticValue () { return nullptr; } + typedef std::shared_ptr SharedPointer; typedef std::unique_ptr AutoPointer; + protected: + lldb::ValueObjectSP + CreateValueObjectFromExpression (const char* name, + const char* expression, + const ExecutionContext& exe_ctx); + + lldb::ValueObjectSP + CreateValueObjectFromAddress (const char* name, + uint64_t address, + const ExecutionContext& exe_ctx, + ClangASTType type); + + lldb::ValueObjectSP + CreateValueObjectFromData (const char* name, + const DataExtractor& data, + const ExecutionContext& exe_ctx, + ClangASTType type); + private: bool m_valid; DISALLOW_COPY_AND_ASSIGN(SyntheticChildrenFrontEnd); }; + class SyntheticValueProviderFrontEnd : public SyntheticChildrenFrontEnd + { + public: + SyntheticValueProviderFrontEnd (ValueObject &backend) : + SyntheticChildrenFrontEnd(backend) + {} + + virtual + ~SyntheticValueProviderFrontEnd () + { + } + + virtual size_t + CalculateNumChildren () { return 0; } + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx) { return nullptr; } + + virtual size_t + GetIndexOfChildWithName (const ConstString &name) { return UINT32_MAX; } + + virtual bool + Update () { return false; } + + virtual bool + MightHaveChildren () { return false; } + + virtual lldb::ValueObjectSP + GetSyntheticValue () = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(SyntheticValueProviderFrontEnd); + }; + class SyntheticChildren { public: @@ -328,37 +383,10 @@ namespace lldb_private { } void - AddExpressionPath (const std::string& path) - { - bool need_add_dot = true; - if (path[0] == '.' || - (path[0] == '-' && path[1] == '>') || - path[0] == '[') - need_add_dot = false; - // add a '.' symbol to help forgetful users - if(!need_add_dot) - m_expression_paths.push_back(path); - else - m_expression_paths.push_back(std::string(".") + path); - } + AddExpressionPath (const std::string& path); bool - SetExpressionPathAtIndex (size_t i, const std::string& path) - { - if (i >= GetCount()) - return false; - bool need_add_dot = true; - if (path[0] == '.' || - (path[0] == '-' && path[1] == '>') || - path[0] == '[') - need_add_dot = false; - // add a '.' symbol to help forgetful users - if(!need_add_dot) - m_expression_paths[i] = path; - else - m_expression_paths[i] = std::string(".") + path; - return true; - } + SetExpressionPathAtIndex (size_t i, const std::string& path); bool IsScripted () @@ -410,24 +438,7 @@ namespace lldb_private { } virtual size_t - GetIndexOfChildWithName (const ConstString &name) - { - const char* name_cstr = name.GetCString(); - for (size_t i = 0; i < filter->GetCount(); i++) - { - const char* expr_cstr = filter->GetExpressionPathAtIndex(i); - if (expr_cstr) - { - if (*expr_cstr == '.') - expr_cstr++; - else if (*expr_cstr == '-' && *(expr_cstr+1) == '>') - expr_cstr += 2; - } - if (!::strcmp(name_cstr, expr_cstr)) - return i; - } - return UINT32_MAX; - } + GetIndexOfChildWithName (const ConstString &name); typedef std::shared_ptr SharedPointer; @@ -548,50 +559,28 @@ namespace lldb_private { ValueObject &backend); bool - IsValid () - { - return m_wrapper_sp.get() != nullptr && m_wrapper_sp->operator bool() && m_interpreter != nullptr; - } + IsValid (); virtual ~FrontEnd (); virtual size_t - CalculateNumChildren () - { - if (!m_wrapper_sp || m_interpreter == NULL) - return 0; - return m_interpreter->CalculateNumChildren(m_wrapper_sp); - } + CalculateNumChildren (); virtual lldb::ValueObjectSP GetChildAtIndex (size_t idx); virtual bool - Update () - { - if (!m_wrapper_sp || m_interpreter == NULL) - return false; - - return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp); - } + Update (); virtual bool - MightHaveChildren () - { - if (!m_wrapper_sp || m_interpreter == NULL) - return false; - - return m_interpreter->MightHaveChildrenSynthProviderInstance(m_wrapper_sp); - } + MightHaveChildren (); virtual size_t - GetIndexOfChildWithName (const ConstString &name) - { - if (!m_wrapper_sp || m_interpreter == NULL) - return UINT32_MAX; - return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp, name.GetCString()); - } + GetIndexOfChildWithName (const ConstString &name); + + virtual lldb::ValueObjectSP + GetSyntheticValue (); typedef std::shared_ptr SharedPointer; diff --git a/include/lldb/DataFormatters/TypeValidator.h b/include/lldb/DataFormatters/TypeValidator.h new file mode 100644 index 000000000000..b501e47943fa --- /dev/null +++ b/include/lldb/DataFormatters/TypeValidator.h @@ -0,0 +1,280 @@ +//===-- TypeValidator.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_TypeValidator_h_ +#define lldb_TypeValidator_h_ + +// C Includes + +// C++ Includes +#include +#include + +// Other libraries and framework includes + +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-private-enumerations.h" + +namespace lldb_private { + +class TypeValidatorImpl +{ +public: + class Flags + { + public: + + Flags () : + m_flags (lldb::eTypeOptionCascade) + {} + + Flags (const Flags& other) : + m_flags (other.m_flags) + {} + + Flags (uint32_t value) : + m_flags (value) + {} + + Flags& + operator = (const Flags& rhs) + { + if (&rhs != this) + m_flags = rhs.m_flags; + + return *this; + } + + Flags& + operator = (const uint32_t& rhs) + { + m_flags = rhs; + return *this; + } + + Flags& + Clear() + { + m_flags = 0; + return *this; + } + + bool + GetCascades () const + { + return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade; + } + + Flags& + SetCascades (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionCascade; + else + m_flags &= ~lldb::eTypeOptionCascade; + return *this; + } + + bool + GetSkipPointers () const + { + return (m_flags & lldb::eTypeOptionSkipPointers) == lldb::eTypeOptionSkipPointers; + } + + Flags& + SetSkipPointers (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionSkipPointers; + else + m_flags &= ~lldb::eTypeOptionSkipPointers; + return *this; + } + + bool + GetSkipReferences () const + { + return (m_flags & lldb::eTypeOptionSkipReferences) == lldb::eTypeOptionSkipReferences; + } + + Flags& + SetSkipReferences (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionSkipReferences; + else + m_flags &= ~lldb::eTypeOptionSkipReferences; + return *this; + } + + uint32_t + GetValue () + { + return m_flags; + } + + void + SetValue (uint32_t value) + { + m_flags = value; + } + + private: + uint32_t m_flags; + }; + + TypeValidatorImpl (const Flags& flags = Flags()); + + typedef std::shared_ptr SharedPointer; + typedef bool(*ValueCallback)(void*, ConstString, const lldb::TypeValidatorImplSP&); + + virtual ~TypeValidatorImpl (); + + bool + Cascades () const + { + return m_flags.GetCascades(); + } + bool + SkipsPointers () const + { + return m_flags.GetSkipPointers(); + } + bool + SkipsReferences () const + { + return m_flags.GetSkipReferences(); + } + + void + SetCascades (bool value) + { + m_flags.SetCascades(value); + } + + void + SetSkipsPointers (bool value) + { + m_flags.SetSkipPointers(value); + } + + void + SetSkipsReferences (bool value) + { + m_flags.SetSkipReferences(value); + } + + uint32_t + GetOptions () + { + return m_flags.GetValue(); + } + + void + SetOptions (uint32_t value) + { + m_flags.SetValue(value); + } + + uint32_t& + GetRevision () + { + return m_my_revision; + } + + enum class Type + { + eTypeUnknown, + eTypeCXX + }; + + struct ValidationResult { + TypeValidatorResult m_result; + std::string m_message; + }; + + virtual Type + GetType () + { + return Type::eTypeUnknown; + } + + // we are using a ValueObject* instead of a ValueObjectSP because we do not need to hold on to this for + // extended periods of time and we trust the ValueObject to stay around for as long as it is required + // for us to generate its value + virtual ValidationResult + FormatObject (ValueObject *valobj) const = 0; + + virtual std::string + GetDescription() = 0; + + static ValidationResult + Success (); + + static ValidationResult + Failure (std::string message); + +protected: + Flags m_flags; + uint32_t m_my_revision; + +private: + DISALLOW_COPY_AND_ASSIGN(TypeValidatorImpl); +}; + +class TypeValidatorImpl_CXX : public TypeValidatorImpl +{ +public: + typedef std::function ValidatorFunction; + + TypeValidatorImpl_CXX (ValidatorFunction f, std::string d, const TypeValidatorImpl::Flags& flags = Flags()); + + typedef std::shared_ptr SharedPointer; + typedef bool(*ValueCallback)(void*, ConstString, const TypeValidatorImpl_CXX::SharedPointer&); + + virtual ~TypeValidatorImpl_CXX (); + + ValidatorFunction + GetValidatorFunction () const + { + return m_validator_function; + } + + void + SetValidatorFunction (ValidatorFunction f) + { + m_validator_function = f; + } + + virtual TypeValidatorImpl::Type + GetType () + { + return TypeValidatorImpl::Type::eTypeCXX; + } + + virtual ValidationResult + FormatObject (ValueObject *valobj) const; + + virtual std::string + GetDescription(); + +protected: + std::string m_description; + ValidatorFunction m_validator_function; + +private: + DISALLOW_COPY_AND_ASSIGN(TypeValidatorImpl_CXX); +}; + + +} // namespace lldb_private + +#endif // lldb_TypeValidator_h_ diff --git a/include/lldb/DataFormatters/ValueObjectPrinter.h b/include/lldb/DataFormatters/ValueObjectPrinter.h index bfe2d9c402d3..235d5389ee75 100644 --- a/include/lldb/DataFormatters/ValueObjectPrinter.h +++ b/include/lldb/DataFormatters/ValueObjectPrinter.h @@ -26,44 +26,43 @@ namespace lldb_private { struct DumpValueObjectOptions { - uint32_t m_max_ptr_depth; - uint32_t m_max_depth; - bool m_show_types; - bool m_show_location; - bool m_use_objc; - lldb::DynamicValueType m_use_dynamic; - bool m_use_synthetic; - bool m_scope_already_checked; - bool m_flat_output; - uint32_t m_omit_summary_depth; - bool m_ignore_cap; - lldb::Format m_format; + uint32_t m_max_ptr_depth = 0; + uint32_t m_max_depth = UINT32_MAX; + lldb::DynamicValueType m_use_dynamic = lldb::eNoDynamicValues; + uint32_t m_omit_summary_depth = 0; + lldb::Format m_format = lldb::eFormatDefault; lldb::TypeSummaryImplSP m_summary_sp; std::string m_root_valobj_name; - bool m_hide_root_type; - bool m_hide_name; - bool m_hide_value; - bool m_be_raw; + bool m_use_synthetic : 1; + bool m_scope_already_checked : 1; + bool m_flat_output : 1; + bool m_ignore_cap : 1; + bool m_show_types : 1; + bool m_show_location : 1; + bool m_use_objc : 1; + bool m_hide_root_type : 1; + bool m_hide_name : 1; + bool m_hide_value : 1; + bool m_run_validator : 1; + bool m_use_type_display_name : 1; + bool m_allow_oneliner_mode : 1; DumpValueObjectOptions() : - m_max_ptr_depth(0), - m_max_depth(UINT32_MAX), - m_show_types(false), - m_show_location(false), - m_use_objc(false), - m_use_dynamic(lldb::eNoDynamicValues), + m_summary_sp(), + m_root_valobj_name(), m_use_synthetic(true), m_scope_already_checked(false), m_flat_output(false), - m_omit_summary_depth(0), m_ignore_cap(false), - m_format (lldb::eFormatDefault), - m_summary_sp(), - m_root_valobj_name(), - m_hide_root_type(false), // provide a special compact display for "po" - m_hide_name(false), // provide a special compact display for "po" - m_hide_value(false), // provide a special compact display for "po" - m_be_raw(false) + m_show_types(false), + m_show_location(false), + m_use_objc(false), + m_hide_root_type(false), + m_hide_name(false), + m_hide_value(false), + m_run_validator(false), + m_use_type_display_name(true), + m_allow_oneliner_mode(true) {} static const DumpValueObjectOptions @@ -74,26 +73,7 @@ struct DumpValueObjectOptions return g_default_options; } - DumpValueObjectOptions (const DumpValueObjectOptions& rhs) : - m_max_ptr_depth(rhs.m_max_ptr_depth), - m_max_depth(rhs.m_max_depth), - m_show_types(rhs.m_show_types), - m_show_location(rhs.m_show_location), - m_use_objc(rhs.m_use_objc), - m_use_dynamic(rhs.m_use_dynamic), - m_use_synthetic(rhs.m_use_synthetic), - m_scope_already_checked(rhs.m_scope_already_checked), - m_flat_output(rhs.m_flat_output), - m_omit_summary_depth(rhs.m_omit_summary_depth), - m_ignore_cap(rhs.m_ignore_cap), - m_format(rhs.m_format), - m_summary_sp(rhs.m_summary_sp), - m_root_valobj_name(rhs.m_root_valobj_name), - m_hide_root_type(rhs.m_hide_root_type), - m_hide_name(rhs.m_hide_name), - m_hide_value(rhs.m_hide_value), - m_be_raw(rhs.m_be_raw) - {} + DumpValueObjectOptions (const DumpValueObjectOptions& rhs) = default; DumpValueObjectOptions& SetMaximumPointerDepth(uint32_t depth = 0) @@ -183,26 +163,15 @@ struct DumpValueObjectOptions } DumpValueObjectOptions& - SetRawDisplay(bool raw = false) + SetRawDisplay() { - if (raw) - { - SetUseSyntheticValue(false); - SetOmitSummaryDepth(UINT32_MAX); - SetIgnoreCap(true); - SetHideName(false); - SetHideValue(false); - m_be_raw = true; - } - else - { - SetUseSyntheticValue(true); - SetOmitSummaryDepth(0); - SetIgnoreCap(false); - SetHideName(false); - SetHideValue(false); - m_be_raw = false; - } + SetUseSyntheticValue(false); + SetOmitSummaryDepth(UINT32_MAX); + SetIgnoreCap(true); + SetHideName(false); + SetHideValue(false); + SetUseTypeDisplayName(false); + SetAllowOnelinerMode(false); return *this; } @@ -250,8 +219,30 @@ struct DumpValueObjectOptions m_hide_value = hide_value; return *this; } -}; + DumpValueObjectOptions& + SetRunValidator (bool run = true) + { + m_run_validator = run; + return *this; + } + + DumpValueObjectOptions& + SetUseTypeDisplayName (bool dis = false) + { + m_use_type_display_name = dis; + return *this; + } + + DumpValueObjectOptions& + SetAllowOnelinerMode (bool oneliner = false) + { + m_allow_oneliner_mode = oneliner; + return *this; + } + +}; + class ValueObjectPrinter { public: @@ -285,7 +276,7 @@ protected: uint32_t curr_depth); bool - GetDynamicValueIfNeeded (); + GetMostSpecializedValue (); const char* GetDescriptionForDisplay (); @@ -296,6 +287,9 @@ protected: bool ShouldPrintValueObject (); + bool + ShouldPrintValidation (); + bool IsNil (); @@ -308,6 +302,12 @@ protected: bool IsAggregate (); + bool + PrintValidationMarkerIfNeeded (); + + bool + PrintValidationErrorIfNeeded (); + bool PrintLocationIfNeeded (); @@ -385,6 +385,7 @@ private: std::string m_value; std::string m_summary; std::string m_error; + std::pair m_validation; friend struct StringSummaryFormat; diff --git a/include/lldb/Expression/ClangExpressionParser.h b/include/lldb/Expression/ClangExpressionParser.h index c79494d1a521..0f578c55942e 100644 --- a/include/lldb/Expression/ClangExpressionParser.h +++ b/include/lldb/Expression/ClangExpressionParser.h @@ -147,6 +147,9 @@ private: std::unique_ptr m_selector_table; ///< Selector table for Objective-C methods std::unique_ptr m_ast_context; ///< The AST context used to hold types and names for the parser std::unique_ptr m_code_generator; ///< The Clang object that generates IR + + class LLDBPreprocessorCallbacks; + LLDBPreprocessorCallbacks *m_pp_callbacks; ///< Called when the preprocessor encounters module imports }; } diff --git a/include/lldb/Expression/ClangExpressionVariable.h b/include/lldb/Expression/ClangExpressionVariable.h index 5ee7a3058946..6c210106d51e 100644 --- a/include/lldb/Expression/ClangExpressionVariable.h +++ b/include/lldb/Expression/ClangExpressionVariable.h @@ -65,6 +65,11 @@ class ClangExpressionVariable public: ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size); + ClangExpressionVariable (ExecutionContextScope *exe_scope, + Value &value, + const ConstString &name, + uint16_t flags = EVNone); + ClangExpressionVariable(const lldb::ValueObjectSP &valobj_sp); //---------------------------------------------------------------------- diff --git a/include/lldb/Expression/ClangFunction.h b/include/lldb/Expression/ClangFunction.h index 61d56729f93d..c122b21be279 100644 --- a/include/lldb/Expression/ClangFunction.h +++ b/include/lldb/Expression/ClangFunction.h @@ -285,9 +285,9 @@ public: /// True if the thread plan may simply be discarded if an error occurs. /// /// @return - /// A ThreadPlan for executing the function. + /// A ThreadPlan shared pointer for executing the function. //------------------------------------------------------------------ - ThreadPlan * + lldb::ThreadPlanSP GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, lldb::addr_t args_addr, const EvaluateExpressionOptions &options, @@ -411,8 +411,10 @@ private: // For ClangFunction only //------------------------------------------------------------------ - std::unique_ptr m_parser; ///< The parser responsible for compiling the function. + // Note: the parser needs to be destructed before the execution unit, so + // declare the the execution unit first. std::shared_ptr m_execution_unit_sp; + std::unique_ptr m_parser; ///< The parser responsible for compiling the function. lldb::ModuleWP m_jit_module_wp; std::string m_name; ///< The name of this clang function - for debugging purposes. diff --git a/include/lldb/Expression/ClangModulesDeclVendor.h b/include/lldb/Expression/ClangModulesDeclVendor.h new file mode 100644 index 000000000000..a35b86a665ff --- /dev/null +++ b/include/lldb/Expression/ClangModulesDeclVendor.h @@ -0,0 +1,58 @@ +//===-- ClangModulesDeclVendor.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef _liblldb_ClangModulesDeclVendor_ +#define _liblldb_ClangModulesDeclVendor_ + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Symbol/DeclVendor.h" +#include "lldb/Target/Platform.h" + +#include + +namespace lldb_private +{ + +class ClangModulesDeclVendor : public DeclVendor +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ClangModulesDeclVendor(); + + virtual + ~ClangModulesDeclVendor(); + + static ClangModulesDeclVendor * + Create(Target &target); + + //------------------------------------------------------------------ + /// Add a module to the list of modules to search. + /// + /// @param[in] path + /// The path to the exact module to be loaded. E.g., if the desired + /// module is std.io, then this should be { "std", "io" }. + /// + /// @param[in] error_stream + /// A stream to populate with the output of the Clang parser when + /// it tries to load the module. + /// + /// @return + /// True if the module could be loaded; false if not. If the + /// compiler encountered a fatal error during a previous module + /// load, then this will always return false for this ModuleImporter. + //------------------------------------------------------------------ + virtual bool + AddModule(std::vector &path, Stream &error_stream) = 0; +}; + +} +#endif /* defined(_lldb_ClangModulesDeclVendor_) */ diff --git a/include/lldb/Expression/ClangUserExpression.h b/include/lldb/Expression/ClangUserExpression.h index 9d2e9093c0bd..f51c9851789a 100644 --- a/include/lldb/Expression/ClangUserExpression.h +++ b/include/lldb/Expression/ClangUserExpression.h @@ -30,8 +30,6 @@ #include "lldb/Symbol/TaggedASTType.h" #include "lldb/Target/ExecutionContext.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" - namespace lldb_private { diff --git a/include/lldb/Expression/IRExecutionUnit.h b/include/lldb/Expression/IRExecutionUnit.h index 3f28351a6928..c15c65c92a3b 100644 --- a/include/lldb/Expression/IRExecutionUnit.h +++ b/include/lldb/Expression/IRExecutionUnit.h @@ -25,7 +25,7 @@ #include "lldb/lldb-private.h" #include "lldb/Core/ClangForward.h" #include "lldb/Core/DataBufferHeap.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "lldb/Expression/ClangExpression.h" #include "lldb/Expression/ClangExpressionParser.h" #include "lldb/Expression/IRMemoryMap.h" @@ -56,7 +56,7 @@ class Error; /// then be used as input to the IR interpreter, or the address of the /// executable code can be passed to a thread plan to run in the target. /// -/// This class creates a subclass of LLVM's JITMemoryManager, because that is +/// This class creates a subclass of LLVM's SectionMemoryManager, because that is /// how the JIT emits code. Because LLDB needs to move JIT-compiled code /// into the target process, the IRExecutionUnit knows how to copy the /// emitted code into the target process. @@ -207,101 +207,12 @@ private: DisassembleFunction (Stream &stream, lldb::ProcessSP &process_sp); - class MemoryManager : public llvm::JITMemoryManager + class MemoryManager : public llvm::SectionMemoryManager { public: MemoryManager (IRExecutionUnit &parent); virtual ~MemoryManager(); - //------------------------------------------------------------------ - /// Passthrough interface stub - //------------------------------------------------------------------ - virtual void setMemoryWritable (); - - //------------------------------------------------------------------ - /// Passthrough interface stub - //------------------------------------------------------------------ - virtual void setMemoryExecutable (); - - //------------------------------------------------------------------ - /// Passthrough interface stub - //------------------------------------------------------------------ - virtual void setPoisonMemory (bool poison) - { - m_default_mm_ap->setPoisonMemory (poison); - } - - //------------------------------------------------------------------ - /// Passthrough interface stub - //------------------------------------------------------------------ - virtual void AllocateGOT() - { - m_default_mm_ap->AllocateGOT(); - } - - //------------------------------------------------------------------ - /// Passthrough interface stub - //------------------------------------------------------------------ - virtual uint8_t *getGOTBase() const - { - return m_default_mm_ap->getGOTBase(); - } - - //------------------------------------------------------------------ - /// Passthrough interface stub - //------------------------------------------------------------------ - virtual uint8_t *startFunctionBody(const llvm::Function *F, - uintptr_t &ActualSize); - - //------------------------------------------------------------------ - /// Allocate room for a dyld stub for a lazy-referenced function, - /// and add it to the m_stubs map - /// - /// @param[in] F - /// The function being referenced. - /// - /// @param[in] StubSize - /// The size of the stub. - /// - /// @param[in] Alignment - /// The required alignment of the stub. - /// - /// @return - /// Allocated space for the stub. - //------------------------------------------------------------------ - virtual uint8_t *allocateStub(const llvm::GlobalValue* F, - unsigned StubSize, - unsigned Alignment); - - //------------------------------------------------------------------ - /// Complete the body of a function, and add it to the m_functions map - /// - /// @param[in] F - /// The function being completed. - /// - /// @param[in] FunctionStart - /// The first instruction of the function. - /// - /// @param[in] FunctionEnd - /// The last byte of the last instruction of the function. - //------------------------------------------------------------------ - virtual void endFunctionBody(const llvm::Function *F, - uint8_t *FunctionStart, - uint8_t *FunctionEnd); - //------------------------------------------------------------------ - /// Allocate space for an unspecified purpose, and add it to the - /// m_spaceBlocks map - /// - /// @param[in] Size - /// The size of the area. - /// - /// @param[in] Alignment - /// The required alignment of the area. - /// - /// @return - /// Allocated space. - //------------------------------------------------------------------ - virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment); //------------------------------------------------------------------ /// Allocate space for executable code, and add it to the @@ -346,22 +257,6 @@ private: llvm::StringRef SectionName, bool IsReadOnly); - //------------------------------------------------------------------ - /// Allocate space for a global variable, and add it to the - /// m_spaceBlocks map - /// - /// @param[in] Size - /// The size of the variable. - /// - /// @param[in] Alignment - /// The required alignment of the variable. - /// - /// @return - /// Allocated space for the global. - //------------------------------------------------------------------ - virtual uint8_t *allocateGlobal(uintptr_t Size, - unsigned Alignment); - //------------------------------------------------------------------ /// Called when object loading is complete and section page /// permissions can be applied. Currently unimplemented for LLDB. @@ -380,52 +275,8 @@ private: return false; } - //------------------------------------------------------------------ - /// Passthrough interface stub - //------------------------------------------------------------------ - virtual void deallocateFunctionBody(void *Body); - - //------------------------------------------------------------------ - /// Passthrough interface stub - //------------------------------------------------------------------ - virtual size_t GetDefaultCodeSlabSize() { - return m_default_mm_ap->GetDefaultCodeSlabSize(); - } - - //------------------------------------------------------------------ - /// Passthrough interface stub - //------------------------------------------------------------------ - virtual size_t GetDefaultDataSlabSize() { - return m_default_mm_ap->GetDefaultDataSlabSize(); - } - - virtual size_t GetDefaultStubSlabSize() { - return m_default_mm_ap->GetDefaultStubSlabSize(); - } - - //------------------------------------------------------------------ - /// Passthrough interface stub - //------------------------------------------------------------------ - virtual unsigned GetNumCodeSlabs() { - return m_default_mm_ap->GetNumCodeSlabs(); - } - - //------------------------------------------------------------------ - /// Passthrough interface stub - //------------------------------------------------------------------ - virtual unsigned GetNumDataSlabs() { - return m_default_mm_ap->GetNumDataSlabs(); - } - - //------------------------------------------------------------------ - /// Passthrough interface stub - //------------------------------------------------------------------ - virtual unsigned GetNumStubSlabs() { - return m_default_mm_ap->GetNumStubSlabs(); - } - virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) { - return m_default_mm_ap->registerEHFrames(Addr, LoadAddr, Size); + return; } //------------------------------------------------------------------ @@ -436,7 +287,7 @@ private: return m_default_mm_ap->getPointerToNamedFunction(Name, AbortOnFailure); } private: - std::unique_ptr m_default_mm_ap; ///< The memory allocator to use in actually creating space. All calls are passed through to it. + std::unique_ptr m_default_mm_ap; ///< The memory allocator to use in actually creating space. All calls are passed through to it. IRExecutionUnit &m_parent; ///< The execution unit this is a proxy for. }; diff --git a/include/lldb/Host/Config.h b/include/lldb/Host/Config.h index af6b98a7912a..7872eb95aab6 100644 --- a/include/lldb/Host/Config.h +++ b/include/lldb/Host/Config.h @@ -14,6 +14,10 @@ #include "lldb/Host/macosx/Config.h" +#elif defined(__ANDROID_NDK__) + +#include "lldb/Host/android/Config.h" + #elif defined(__linux__) || defined(__GNU__) #include "lldb/Host/linux/Config.h" diff --git a/include/lldb/Host/ConnectionFileDescriptor.h b/include/lldb/Host/ConnectionFileDescriptor.h new file mode 100644 index 000000000000..0d486a34c8d0 --- /dev/null +++ b/include/lldb/Host/ConnectionFileDescriptor.h @@ -0,0 +1,15 @@ +//===-- ConnectionFileDescriptor.h ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Host_ConnectionFileDescriptor_h_ +#define liblldb_Host_ConnectionFileDescriptor_h_ + +#include "lldb/Host/posix/ConnectionFileDescriptorPosix.h" + +#endif diff --git a/include/lldb/Host/Editline.h b/include/lldb/Host/Editline.h index 5cba8465d654..9fce193efc9f 100644 --- a/include/lldb/Host/Editline.h +++ b/include/lldb/Host/Editline.h @@ -7,202 +7,360 @@ // //===----------------------------------------------------------------------===// +//TODO: wire up window size changes + +// If we ever get a private copy of libedit, there are a number of defects that would be nice to fix; +// a) Sometimes text just disappears while editing. In an 80-column editor paste the following text, without +// the quotes: +// "This is a test of the input system missing Hello, World! Do you disappear when it gets to a particular length?" +// Now press ^A to move to the start and type 3 characters, and you'll see a good amount of the text will +// disappear. It's still in the buffer, just invisible. +// b) The prompt printing logic for dealing with ANSI formatting characters is broken, which is why we're +// working around it here. +// c) When resizing the terminal window, if the cursor moves between rows libedit will get confused. +// d) The incremental search uses escape to cancel input, so it's confused by ANSI sequences starting with escape. +// e) Emoji support is fairly terrible, presumably it doesn't understand composed characters? + #ifndef liblldb_Editline_h_ #define liblldb_Editline_h_ #if defined(__cplusplus) +#include +#include + +// components needed to handle wide characters ( , codecvt_utf8, libedit built with '--enable-widec' ) +// are not consistenly available on non-OSX platforms. The wchar_t versions of libedit functions will only be +// used in cases where this is true. This is a compile time dependecy, for now selected per target Platform +#if defined (__APPLE__) +#define LLDB_EDITLINE_USE_WCHAR 1 +#include +#else +#define LLDB_EDITLINE_USE_WCHAR 0 +#endif + #include "lldb/lldb-private.h" +#include "lldb/Host/ConnectionFileDescriptor.h" -#include -#ifdef _WIN32 +#if defined(_WIN32) #include "lldb/Host/windows/editlinewin.h" #else +#if !defined(__ANDROID_NDK__) #include #endif +#endif #include #include -#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Host/Condition.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/Mutex.h" #include "lldb/Host/Predicate.h" namespace lldb_private { + namespace line_editor { -//---------------------------------------------------------------------- -/// @class Editline Editline.h "lldb/Host/Editline.h" -/// @brief A class that encapsulates editline functionality. -//---------------------------------------------------------------------- -class EditlineHistory; - -typedef std::shared_ptr EditlineHistorySP; - -class Editline -{ -public: - typedef LineStatus (*LineCompletedCallbackType) ( - Editline *editline, - StringList &lines, - uint32_t line_idx, - Error &error, - void *baton); - - typedef int (*CompleteCallbackType) ( - const char *current_line, - const char *cursor, - const char *last_char, - int skip_first_n_matches, - int max_matches, - StringList &matches, - void *baton); - - typedef int (*GetCharCallbackType) ( - ::EditLine *, - char *c); - - Editline(const char *prog, // Used for the history file and for editrc program name - const char *prompt, - bool configure_for_multiline, - FILE *fin, - FILE *fout, - FILE *ferr); - - ~Editline(); - - Error - GetLine (std::string &line, - bool &interrupted); - - Error - GetLines (const std::string &end_line, - StringList &lines, - bool &interrupted); - - bool - LoadHistory (); - - bool - SaveHistory (); - - FILE * - GetInputFile (); - - FILE * - GetOutputFile (); - - FILE * - GetErrorFile (); - - bool - GettingLine () const - { - return m_getting_line; - } - - void - Hide (); + // type alias's to help manage 8 bit and wide character versions of libedit +#if LLDB_EDITLINE_USE_WCHAR + using EditLineStringType = std::wstring; + using EditLineStringStreamType = std::wstringstream; + using EditLineCharType = wchar_t; +#else + using EditLineStringType=std::string; + using EditLineStringStreamType = std::stringstream; + using EditLineCharType = char; +#endif - void - Refresh(); + typedef int (* EditlineGetCharCallbackType)(::EditLine * editline, EditLineCharType * c); + typedef unsigned char (* EditlineCommandCallbackType)(::EditLine * editline, int ch); + typedef const char * (* EditlinePromptCallbackType)(::EditLine * editline); - bool - Interrupt (); + class EditlineHistory; + + typedef std::shared_ptr EditlineHistorySP; - void - SetAutoCompleteCallback (CompleteCallbackType callback, - void *baton) - { - m_completion_callback = callback; - m_completion_callback_baton = baton; - } + typedef bool (* IsInputCompleteCallbackType) ( + Editline * editline, + StringList & lines, + void * baton); + + typedef int (* FixIndentationCallbackType) ( + Editline * editline, + const StringList & lines, + int cursor_position, + void * baton); + + typedef int (* CompleteCallbackType) ( + const char * current_line, + const char * cursor, + const char * last_char, + int skip_first_n_matches, + int max_matches, + StringList & matches, + void * baton); + + /// Status used to decide when and how to start editing another line in multi-line sessions + enum class EditorStatus + { + + /// The default state proceeds to edit the current line + Editing, + + /// Editing complete, returns the complete set of edited lines + Complete, + + /// End of input reported + EndOfInput, - void - SetLineCompleteCallback (LineCompletedCallbackType callback, - void *baton) - { - m_line_complete_callback = callback; - m_line_complete_callback_baton = baton; + /// Editing interrupted + Interrupted + }; + + /// Established locations that can be easily moved among with MoveCursor + enum class CursorLocation + { + /// The start of the first line in a multi-line edit session + BlockStart, + + /// The start of the current line in a multi-line edit session + EditingPrompt, + + /// The location of the cursor on the current line in a multi-line edit session + EditingCursor, + + /// The location immediately after the last character in a multi-line edit session + BlockEnd + }; } - - size_t - Push (const char *bytes, size_t len); - - static int - GetCharFromInputFileCallback (::EditLine *e, char *c); - - void - SetGetCharCallback (GetCharCallbackType callback); - const char * - GetPrompt(); + using namespace line_editor; - void - SetPrompt (const char *p); - - void - ShowLineNumbers (bool enable, uint32_t line_offset) + /// Instances of Editline provide an abstraction over libedit's EditLine facility. Both + /// single- and multi-line editing are supported. + class Editline { - m_prompt_with_line_numbers = enable; - m_line_offset = line_offset; - } - -private: + public: + Editline (const char * editor_name, FILE * input_file, FILE * output_file, FILE * error_file, bool color_prompts); + + ~Editline(); + + /// Uses the user data storage of EditLine to retrieve an associated instance of Editline. + static Editline * + InstanceFor (::EditLine * editline); + + /// Sets a string to be used as a prompt, or combined with a line number to form a prompt. + void + SetPrompt (const char * prompt); + + /// Sets an alternate string to be used as a prompt for the second line and beyond in multi-line + /// editing scenarios. + void + SetContinuationPrompt (const char * continuation_prompt); + + /// Required to update the width of the terminal registered for I/O. It is critical that this + /// be correct at all times. + void + TerminalSizeChanged(); + + /// Returns the prompt established by SetPrompt() + const char * + GetPrompt(); + + /// Returns the index of the line currently being edited + uint32_t + GetCurrentLine(); - Error - PrivateGetLine(std::string &line); - - unsigned char - HandleCompletion (int ch); + /// Hides the current input session in preparation for output + void + Hide(); + + /// Prepare to return to editing after a call to Hide() + void + Refresh(); - static unsigned char - CallbackEditPrevLine (::EditLine *e, int ch); - - static unsigned char - CallbackEditNextLine (::EditLine *e, int ch); - - static unsigned char - CallbackComplete (::EditLine *e, int ch); + /// Interrupt the current edit as if ^C was pressed + bool + Interrupt(); + + /// Register a callback for the tab key + void + SetAutoCompleteCallback (CompleteCallbackType callback, void * baton); + + /// Register a callback for testing whether multi-line input is complete + void + SetIsInputCompleteCallback (IsInputCompleteCallbackType callback, void * baton); + + /// Register a callback for determining the appropriate indentation for a line + /// when creating a newline. An optional set of insertable characters can also + /// trigger the callback. + bool + SetFixIndentationCallback (FixIndentationCallbackType callback, + void * baton, + const char * indent_chars); - static const char * - GetPromptCallback (::EditLine *e); + /// Prompts for and reads a single line of user input. + bool + GetLine (std::string &line, bool &interrupted); + + /// Prompts for and reads a multi-line batch of user input. + bool + GetLines (int first_line_number, StringList &lines, bool &interrupted); + + private: + + /// Sets the lowest line number for multi-line editing sessions. A value of zero suppresses + /// line number printing in the prompt. + void + SetBaseLineNumber (int line_number); + + /// Returns the complete prompt by combining the prompt or continuation prompt with line numbers + /// as appropriate. The line index is a zero-based index into the current multi-line session. + std::string + PromptForIndex (int line_index); + + /// Sets the current line index between line edits to allow free movement between lines. Updates + /// the prompt to match. + void + SetCurrentLine (int line_index); + + /// Determines the width of the prompt in characters. The width is guaranteed to be the same for + /// all lines of the current multi-line session. + int + GetPromptWidth(); + + /// Returns true if the underlying EditLine session's keybindings are Emacs-based, or false if + /// they are VI-based. + bool + IsEmacs(); + + /// Returns true if the current EditLine buffer contains nothing but spaces, or is empty. + bool + IsOnlySpaces(); + + /// Helper method used by MoveCursor to determine relative line position. + int + GetLineIndexForLocation (CursorLocation location, int cursor_row); + + /// Move the cursor from one well-established location to another using relative line positioning + /// and absolute column positioning. + void + MoveCursor (CursorLocation from, CursorLocation to); + + /// Clear from cursor position to bottom of screen and print input lines including prompts, optionally + /// starting from a specific line. Lines are drawn with an extra space at the end to reserve room for + /// the rightmost cursor position. + void + DisplayInput (int firstIndex = 0); + + /// Counts the number of rows a given line of content will end up occupying, taking into account both + /// the preceding prompt and a single trailing space occupied by a cursor when at the end of the line. + int + CountRowsForLine (const EditLineStringType & content); + + /// Save the line currently being edited + void + SaveEditedLine(); + + /// Convert the current input lines into a UTF8 StringList + StringList + GetInputAsStringList(int line_count = UINT32_MAX); + + /// Replaces the current multi-line session with the next entry from history. When the parameter is + /// true it will take the next earlier entry from history, when it is false it takes the next most + /// recent. + unsigned char + RecallHistory (bool earlier); + + /// Character reading implementation for EditLine that supports our multi-line editing trickery. + int + GetCharacter (EditLineCharType * c); + + /// Prompt implementation for EditLine. + const char * + Prompt(); + + /// Line break command used when return is pressed in multi-line mode. + unsigned char + BreakLineCommand (int ch); + + /// Delete command used when delete is pressed in multi-line mode. + unsigned char + DeleteNextCharCommand (int ch); + + /// Delete command used when backspace is pressed in multi-line mode. + unsigned char + DeletePreviousCharCommand (int ch); + + /// Line navigation command used when ^P or up arrow are pressed in multi-line mode. + unsigned char + PreviousLineCommand (int ch); + + /// Line navigation command used when ^N or down arrow are pressed in multi-line mode. + unsigned char + NextLineCommand (int ch); + + /// Buffer start command used when Esc < is typed in multi-line emacs mode. + unsigned char + BufferStartCommand (int ch); + + /// Buffer end command used when Esc > is typed in multi-line emacs mode. + unsigned char + BufferEndCommand (int ch); - static Editline * - GetClientData (::EditLine *e); - - static FILE * - GetFilePointer (::EditLine *e, int fd); + /// Context-sensitive tab insertion or code completion command used when the tab key is typed. + unsigned char + TabCommand (int ch); + + /// Respond to normal character insertion by fixing line indentation + unsigned char + FixIndentationCommand (int ch); - enum class Command - { - None = 0, - EditPrevLine, - EditNextLine, - }; - ::EditLine *m_editline; - EditlineHistorySP m_history_sp; - std::string m_prompt; - std::string m_lines_prompt; - lldb_private::Predicate m_getting_char; - CompleteCallbackType m_completion_callback; - void *m_completion_callback_baton; - LineCompletedCallbackType m_line_complete_callback; - void *m_line_complete_callback_baton; - Command m_lines_command; - uint32_t m_line_offset; - uint32_t m_lines_curr_line; - uint32_t m_lines_max_line; - ConnectionFileDescriptor m_file; - bool m_prompt_with_line_numbers; - bool m_getting_line; - bool m_got_eof; // Set to true when we detect EOF - bool m_interrupted; - - DISALLOW_COPY_AND_ASSIGN(Editline); -}; + /// Revert line command used when moving between lines. + unsigned char + RevertLineCommand (int ch); -} // namespace lldb_private + /// Ensures that the current EditLine instance is properly configured for single or multi-line editing. + void + ConfigureEditor (bool multiline); + + private: +#if LLDB_EDITLINE_USE_WCHAR + std::wstring_convert> m_utf8conv; +#endif + ::EditLine * m_editline = nullptr; + EditlineHistorySP m_history_sp; + bool m_in_history = false; + std::vector m_live_history_lines; + bool m_multiline_enabled = false; + std::vector m_input_lines; + EditorStatus m_editor_status; + bool m_editor_getting_char = false; + bool m_color_prompts = true; + int m_terminal_width = 0; + int m_base_line_number = 0; + unsigned m_current_line_index = 0; + int m_current_line_rows = -1; + int m_revert_cursor_index = 0; + int m_line_number_digits = 3; + std::string m_set_prompt; + std::string m_set_continuation_prompt; + std::string m_current_prompt; + bool m_needs_prompt_repaint = false; + std::string m_editor_name; + FILE * m_input_file; + FILE * m_output_file; + FILE * m_error_file; + ConnectionFileDescriptor m_input_connection; + IsInputCompleteCallbackType m_is_input_complete_callback = nullptr; + void * m_is_input_complete_callback_baton = nullptr; + FixIndentationCallbackType m_fix_indentation_callback = nullptr; + void * m_fix_indentation_callback_baton = nullptr; + const char * m_fix_indentation_callback_chars = nullptr; + CompleteCallbackType m_completion_callback = nullptr; + void * m_completion_callback_baton = nullptr; + }; +} #endif // #if defined(__cplusplus) -#endif // liblldb_Host_h_ +#endif // liblldb_Editline_h_ diff --git a/include/lldb/Host/FileSpec.h b/include/lldb/Host/FileSpec.h index ef73bb2ede0f..173d948e687b 100644 --- a/include/lldb/Host/FileSpec.h +++ b/include/lldb/Host/FileSpec.h @@ -246,7 +246,7 @@ public: Compare (const FileSpec& lhs, const FileSpec& rhs, bool full); static bool - Equal (const FileSpec& a, const FileSpec& b, bool full); + Equal (const FileSpec& a, const FileSpec& b, bool full, bool remove_backups = false); //------------------------------------------------------------------ /// Dump this object to a Stream. @@ -582,6 +582,20 @@ public: static void Normalize(llvm::SmallVectorImpl &path, PathSyntax syntax = ePathSyntaxHostNative); static void DeNormalize(llvm::SmallVectorImpl &path, PathSyntax syntax = ePathSyntaxHostNative); + + //------------------------------------------------------------------ + /// Run through the input string, replaying the effect of any ".." and produce + /// the resultant path. The input path is not required to be in the host file system + /// format, but it is required to be normalized to that system. + /// + /// @param[in] input + /// The input path to analyze. + /// + /// @param[out] result + /// The backup-resolved path will be written here. + //------------------------------------------------------------------ + static void RemoveBackupDots (const ConstString &input_const_str, ConstString &result_const_str); + //------------------------------------------------------------------ /// Change the file specified with a new path. /// diff --git a/include/lldb/Host/Host.h b/include/lldb/Host/Host.h index 19ed7b01e80f..ce12689fc047 100644 --- a/include/lldb/Host/Host.h +++ b/include/lldb/Host/Host.h @@ -21,6 +21,7 @@ #include "lldb/Core/StringList.h" #include "lldb/Host/File.h" #include "lldb/Host/FileSpec.h" +#include "lldb/Host/HostThread.h" namespace lldb_private { @@ -38,9 +39,6 @@ class Host { public: - /// A value of std::numeric_limits::max() is used if there is no practical limit. - static const uint32_t MAX_THREAD_NAME_LENGTH; - typedef bool (*MonitorChildProcessCallback) (void *callback_baton, lldb::pid_t pid, bool exited, @@ -86,11 +84,8 @@ public: /// /// @see static void Host::StopMonitoringChildProcess (uint32_t) //------------------------------------------------------------------ - static lldb::thread_t - StartMonitoringChildProcess (MonitorChildProcessCallback callback, - void *callback_baton, - lldb::pid_t pid, - bool monitor_signals); + static HostThread StartMonitoringChildProcess(MonitorChildProcessCallback callback, void *callback_baton, lldb::pid_t pid, + bool monitor_signals); enum SystemLogType { @@ -140,36 +135,6 @@ public: static void WillTerminate (); - //------------------------------------------------------------------ - /// Host specific thread created function call. - /// - /// This function call lets the current host OS do any thread - /// specific initialization that it needs, including naming the - /// thread. No cleanup routine is expected to be called - /// - /// @param[in] name - /// The current thread's name in the current process. - //------------------------------------------------------------------ - static void - ThreadCreated (const char *name); - - static lldb::thread_t - ThreadCreate (const char *name, - lldb::thread_func_t function, - lldb::thread_arg_t thread_arg, - Error *err); - - static bool - ThreadCancel (lldb::thread_t thread, - Error *error); - - static bool - ThreadDetach (lldb::thread_t thread, - Error *error); - static bool - ThreadJoin (lldb::thread_t thread, - lldb::thread_result_t *thread_result_ptr, - Error *error); typedef void (*ThreadLocalStorageCleanupCallback) (void *p); @@ -182,65 +147,6 @@ public: static void ThreadLocalStorageSet(lldb::thread_key_t key, void *value); - //------------------------------------------------------------------ - /// Gets the name of a thread in a process. - /// - /// This function will name a thread in a process using it's own - /// thread name pool, and also will attempt to set a thread name - /// using any supported host OS APIs. - /// - /// @param[in] pid - /// The process ID in which we are trying to get the name of - /// a thread. - /// - /// @param[in] tid - /// The thread ID for which we are trying retrieve the name of. - /// - /// @return - /// A std::string containing the thread name. - //------------------------------------------------------------------ - static std::string - GetThreadName (lldb::pid_t pid, lldb::tid_t tid); - - //------------------------------------------------------------------ - /// Sets the name of a thread in the current process. - /// - /// @param[in] pid - /// The process ID in which we are trying to name a thread. - /// - /// @param[in] tid - /// The thread ID which we are trying to name. - /// - /// @param[in] name - /// The current thread's name in the current process to \a name. - /// - /// @return - /// \b true if the thread name was able to be set, \b false - /// otherwise. - //------------------------------------------------------------------ - static bool - SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name); - - //------------------------------------------------------------------ - /// Sets a shortened name of a thread in the current process. - /// - /// @param[in] pid - /// The process ID in which we are trying to name a thread. - /// - /// @param[in] tid - /// The thread ID which we are trying to name. - /// - /// @param[in] name - /// The current thread's name in the current process to \a name. - /// - /// @param[in] len - /// The maximum length for the thread's shortened name. - /// - /// @return - /// \b true if the thread name was able to be set, \b false - /// otherwise. - static bool - SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name, size_t len); //------------------------------------------------------------------ /// Given an address in the current process (the process that @@ -330,11 +236,9 @@ public: GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info); #if defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined (__NetBSD__) - static short - GetPosixspawnFlags (ProcessLaunchInfo &launch_info); + static short GetPosixspawnFlags(const ProcessLaunchInfo &launch_info); - static Error - LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid); + static Error LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &launch_info, lldb::pid_t &pid); static bool AddPosixSpawnFileAction(void *file_actions, const FileAction *info, Log *log, Error &error); #endif @@ -355,7 +259,7 @@ public: int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit std::string *command_output, // Pass NULL if you don't want the command output uint32_t timeout_sec, - const char *shell = LLDB_DEFAULT_SHELL); + bool run_in_default_shell = true); static lldb::DataBufferSP GetAuxvData (lldb_private::Process *process); @@ -363,9 +267,6 @@ public: static lldb::DataBufferSP GetAuxvData (lldb::pid_t pid); - static lldb::TargetSP - GetDummyTarget (Debugger &debugger); - static bool OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no); diff --git a/include/lldb/Host/HostInfoBase.h b/include/lldb/Host/HostInfoBase.h index f890dbc0b01b..5a8a06329500 100644 --- a/include/lldb/Host/HostInfoBase.h +++ b/include/lldb/Host/HostInfoBase.h @@ -44,6 +44,14 @@ class HostInfoBase //------------------------------------------------------------------ static uint32_t GetNumberCPUS(); + //------------------------------------------------------------------ + /// Returns the maximum length of a thread name on this platform. + /// + /// @return + /// Maximum length of a thread name on this platform. + //------------------------------------------------------------------ + static uint32_t GetMaxThreadNameLength(); + //------------------------------------------------------------------ /// Gets the host vendor string. /// @@ -110,6 +118,7 @@ class HostInfoBase static bool ComputeTempFileDirectory(FileSpec &file_spec); static bool ComputeHeaderDirectory(FileSpec &file_spec); static bool ComputeSystemPluginsDirectory(FileSpec &file_spec); + static bool ComputeClangDirectory(FileSpec &file_spec); static bool ComputeUserPluginsDirectory(FileSpec &file_spec); static void ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64); diff --git a/include/lldb/Host/HostNativeProcess.h b/include/lldb/Host/HostNativeProcess.h new file mode 100644 index 000000000000..b48956436116 --- /dev/null +++ b/include/lldb/Host/HostNativeProcess.h @@ -0,0 +1,27 @@ +//===-- HostNativeProcess.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_HostNativeProcess_h_ +#define lldb_Host_HostNativeProcess_h_ + +#if defined(_WIN32) +#include "lldb/Host/windows/HostProcessWindows.h" +namespace lldb_private +{ +typedef HostProcessWindows HostNativeProcess; +} +#else +#include "lldb/Host/posix/HostProcessPosix.h" +namespace lldb_private +{ +typedef HostProcessPosix HostNativeProcess; +} +#endif + +#endif diff --git a/include/lldb/Host/HostNativeProcessBase.h b/include/lldb/Host/HostNativeProcessBase.h new file mode 100644 index 000000000000..ba16bf2b876f --- /dev/null +++ b/include/lldb/Host/HostNativeProcessBase.h @@ -0,0 +1,57 @@ +//===-- HostNativeProcessBase.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_HostNativeProcessBase_h_ +#define lldb_Host_HostNativeProcessBase_h_ + +#include "lldb/Core/Error.h" +#include "lldb/Host/HostProcess.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-types.h" + +namespace lldb_private +{ + +class HostThread; + +class HostNativeProcessBase +{ + DISALLOW_COPY_AND_ASSIGN(HostNativeProcessBase); + + public: + HostNativeProcessBase() + : m_process(LLDB_INVALID_PROCESS) + { + } + explicit HostNativeProcessBase(lldb::process_t process) + : m_process(process) + {} + virtual ~HostNativeProcessBase() {} + + virtual Error Terminate() = 0; + virtual Error GetMainModule(FileSpec &file_spec) const = 0; + + virtual lldb::pid_t GetProcessId() const = 0; + virtual bool IsRunning() const = 0; + + lldb::process_t + GetSystemHandle() const + { + return m_process; + } + + virtual HostThread StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals) = 0; + + protected: + lldb::process_t m_process; +}; + +} + +#endif diff --git a/include/lldb/Host/HostNativeThread.h b/include/lldb/Host/HostNativeThread.h new file mode 100644 index 000000000000..f39c775df8e3 --- /dev/null +++ b/include/lldb/Host/HostNativeThread.h @@ -0,0 +1,25 @@ +//===-- HostNativeThread.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_HostNativeThread_h_ +#define lldb_Host_HostNativeThread_h_ + +#include "HostNativeThreadForward.h" + +#if defined(_WIN32) +#include "lldb/Host/windows/HostThreadWindows.h" +#elif defined(__linux__) +#include "lldb/Host/linux/HostThreadLinux.h" +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#include "lldb/Host/freebsd/HostThreadFreeBSD.h" +#elif defined(__APPLE__) +#include "lldb/Host/macosx/HostThreadMacOSX.h" +#endif + +#endif diff --git a/include/lldb/Host/HostNativeThreadBase.h b/include/lldb/Host/HostNativeThreadBase.h new file mode 100644 index 000000000000..c89c6e16533e --- /dev/null +++ b/include/lldb/Host/HostNativeThreadBase.h @@ -0,0 +1,53 @@ +//===-- HostNativeThreadBase.h ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_HostNativeThreadBase_h_ +#define lldb_Host_HostNativeThreadBase_h_ + +#include "lldb/Core/Error.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-types.h" + +namespace lldb_private +{ + +#if defined(_WIN32) +#define THREAD_ROUTINE __stdcall +#else +#define THREAD_ROUTINE +#endif + +class HostNativeThreadBase +{ + friend class ThreadLauncher; + DISALLOW_COPY_AND_ASSIGN(HostNativeThreadBase); + + public: + HostNativeThreadBase(); + explicit HostNativeThreadBase(lldb::thread_t thread); + virtual ~HostNativeThreadBase() {} + + virtual Error Join(lldb::thread_result_t *result) = 0; + virtual Error Cancel() = 0; + virtual bool IsJoinable() const; + virtual void Reset(); + lldb::thread_t Release(); + + lldb::thread_t GetSystemHandle() const; + lldb::thread_result_t GetResult() const; + + protected: + static lldb::thread_result_t THREAD_ROUTINE ThreadCreateTrampoline(lldb::thread_arg_t arg); + + lldb::thread_t m_thread; + lldb::thread_result_t m_result; +}; +} + +#endif diff --git a/include/lldb/Host/HostNativeThreadForward.h b/include/lldb/Host/HostNativeThreadForward.h new file mode 100644 index 000000000000..e6bd426673b3 --- /dev/null +++ b/include/lldb/Host/HostNativeThreadForward.h @@ -0,0 +1,30 @@ +//===-- HostNativeThreadForward.h -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_HostNativeThreadForward_h_ +#define lldb_Host_HostNativeThreadForward_h_ + +namespace lldb_private +{ +#if defined(_WIN32) +class HostThreadWindows; +typedef HostThreadWindows HostNativeThread; +#elif defined(__linux__) +class HostThreadLinux; +typedef HostThreadLinux HostNativeThread; +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +class HostThreadFreeBSD; +typedef HostThreadFreeBSD HostNativeThread; +#elif defined(__APPLE__) +class HostThreadMacOSX; +typedef HostThreadMacOSX HostNativeThread; +#endif +} + +#endif diff --git a/include/lldb/Host/HostProcess.h b/include/lldb/Host/HostProcess.h index 2c10709ce942..aff779aee219 100644 --- a/include/lldb/Host/HostProcess.h +++ b/include/lldb/Host/HostProcess.h @@ -10,6 +10,8 @@ #ifndef lldb_Host_HostProcess_h_ #define lldb_Host_HostProcess_h_ +#include "lldb/lldb-types.h" + //---------------------------------------------------------------------- /// @class HostInfo HostInfo.h "lldb/Host/HostProcess.h" /// @brief A class that represents a running process on the host machine. @@ -26,19 +28,36 @@ /// //---------------------------------------------------------------------- -#if defined(_WIN32) -#include "lldb/Host/windows/HostProcessWindows.h" -#define HOST_PROCESS_TYPE HostProcessWindows -#else -#include "lldb/Host/posix/HostProcessPosix.h" -#define HOST_PROCESS_TYPE HostProcessPosix -#endif - namespace lldb_private { - typedef HOST_PROCESS_TYPE HostProcess; -} -#undef HOST_PROCESS_TYPE +class HostNativeProcessBase; +class HostThread; + +class HostProcess +{ + public: + typedef bool (*MonitorCallback)(void *callback_baton, lldb::pid_t process, bool exited, int signal, int status); + + HostProcess(); + HostProcess(lldb::process_t process); + ~HostProcess(); + + Error Terminate(); + Error GetMainModule(FileSpec &file_spec) const; + + lldb::pid_t GetProcessId() const; + bool IsRunning() const; + + HostThread StartMonitoring(MonitorCallback callback, void *callback_baton, bool monitor_signals); + + HostNativeProcessBase &GetNativeProcess(); + const HostNativeProcessBase &GetNativeProcess() const; + + private: + std::shared_ptr m_native_process; +}; + +} #endif diff --git a/include/lldb/Host/HostThread.h b/include/lldb/Host/HostThread.h new file mode 100644 index 000000000000..9fdf9f9618b5 --- /dev/null +++ b/include/lldb/Host/HostThread.h @@ -0,0 +1,56 @@ +//===-- HostThread.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_HostThread_h_ +#define lldb_Host_HostThread_h_ + +#include "lldb/Core/Error.h" +#include "lldb/Host/HostNativeThreadForward.h" +#include "lldb/lldb-types.h" + +#include + +namespace lldb_private +{ + +class HostNativeThreadBase; + +//---------------------------------------------------------------------- +/// @class HostInfo HostInfo.h "lldb/Host/HostThread.h" +/// @brief A class that represents a thread running inside of a process on the +/// local machine. +/// +/// HostThread allows querying and manipulation of threads running on the host +/// machine. +/// +//---------------------------------------------------------------------- +class HostThread +{ + public: + HostThread(); + HostThread(lldb::thread_t thread); + + Error Join(lldb::thread_result_t *result); + Error Cancel(); + void Reset(); + lldb::thread_t Release(); + + bool IsJoinable() const; + HostNativeThread &GetNativeThread(); + const HostNativeThread &GetNativeThread() const; + lldb::thread_result_t GetResult() const; + + bool EqualsThread(lldb::thread_t thread) const; + + private: + std::shared_ptr m_native_thread; +}; +} + +#endif diff --git a/include/lldb/Host/MonitoringProcessLauncher.h b/include/lldb/Host/MonitoringProcessLauncher.h new file mode 100644 index 000000000000..3c3e66108f8a --- /dev/null +++ b/include/lldb/Host/MonitoringProcessLauncher.h @@ -0,0 +1,30 @@ +//===-- MonitoringProcessLauncher.h -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_MonitoringProcessLauncher_h_ +#define lldb_Host_MonitoringProcessLauncher_h_ + +#include "lldb/Host/ProcessLauncher.h" + +namespace lldb_private +{ + +class MonitoringProcessLauncher : public ProcessLauncher +{ + public: + explicit MonitoringProcessLauncher(std::unique_ptr delegate_launcher); + + virtual HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error); + + private: + std::unique_ptr m_delegate_launcher; +}; +} + +#endif diff --git a/include/lldb/Host/Pipe.h b/include/lldb/Host/Pipe.h index b36c85cfbe87..a5502efa78ed 100644 --- a/include/lldb/Host/Pipe.h +++ b/include/lldb/Host/Pipe.h @@ -7,77 +7,21 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_Pipe_h_ -#define liblldb_Pipe_h_ -#if defined(__cplusplus) +#ifndef liblldb_Host_Pipe_h_ +#define liblldb_Host_Pipe_h_ -#include -#include -#include - -#include "lldb/lldb-private.h" - -namespace lldb_private { - -//---------------------------------------------------------------------- -/// @class Pipe Pipe.h "lldb/Host/Pipe.h" -/// @brief A class that abtracts unix style pipes. -/// -/// A class that abstracts the LLDB core from host pipe functionality. -//---------------------------------------------------------------------- -class Pipe +#if defined(_WIN32) +#include "lldb/Host/windows/PipeWindows.h" +namespace lldb_private { -public: - static int kInvalidDescriptor; - - Pipe(); - - ~Pipe(); - - bool - Open(); - - bool - IsValid() const; - - bool - ReadDescriptorIsValid() const; - - bool - WriteDescriptorIsValid() const; - - int - GetReadFileDescriptor() const; - - int - GetWriteFileDescriptor() const; - - // Close both descriptors - void - Close(); - - bool - CloseReadFileDescriptor(); - - bool - CloseWriteFileDescriptor(); - - int - ReleaseReadFileDescriptor(); - - int - ReleaseWriteFileDescriptor(); - - size_t - Read (void *buf, size_t size); - - size_t - Write (const void *buf, size_t size); -private: - int m_fds[2]; -}; - -} // namespace lldb_private +typedef PipeWindows Pipe; +} +#else +#include "lldb/Host/posix/PipePosix.h" +namespace lldb_private +{ +typedef PipePosix Pipe; +} +#endif -#endif // #if defined(__cplusplus) -#endif // liblldb_Pipe_h_ +#endif // liblldb_Host_Pipe_h_ diff --git a/include/lldb/Host/PipeBase.h b/include/lldb/Host/PipeBase.h new file mode 100644 index 000000000000..8cad2507d32c --- /dev/null +++ b/include/lldb/Host/PipeBase.h @@ -0,0 +1,54 @@ +//===-- PipeBase.h -----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Host_PipeBase_h_ +#define liblldb_Host_PipeBase_h_ + +#include +#include + +#include "lldb/Core/Error.h" +#include "llvm/ADT/StringRef.h" + +namespace lldb_private +{ +class PipeBase +{ + public: + virtual ~PipeBase(); + + virtual Error CreateNew(bool child_process_inherit) = 0; + virtual Error CreateNew(llvm::StringRef name, bool child_process_inherit) = 0; + + virtual Error OpenAsReader(llvm::StringRef name, bool child_process_inherit) = 0; + + Error OpenAsWriter(llvm::StringRef name, bool child_process_inherit); + virtual Error OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) = 0; + + virtual bool CanRead() const = 0; + virtual bool CanWrite() const = 0; + + virtual int GetReadFileDescriptor() const = 0; + virtual int GetWriteFileDescriptor() const = 0; + virtual int ReleaseReadFileDescriptor() = 0; + virtual int ReleaseWriteFileDescriptor() = 0; + + // Close both descriptors + virtual void Close() = 0; + + // Delete named pipe. + virtual Error Delete(llvm::StringRef name) = 0; + + virtual Error Write(const void *buf, size_t size, size_t &bytes_written) = 0; + virtual Error ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read) = 0; + Error Read(void *buf, size_t size, size_t &bytes_read); +}; +} + +#endif diff --git a/include/lldb/Host/Predicate.h b/include/lldb/Host/Predicate.h index f0e83ea5894b..ae6c99155fe0 100644 --- a/include/lldb/Host/Predicate.h +++ b/include/lldb/Host/Predicate.h @@ -11,6 +11,7 @@ #define liblldb_Predicate_h_ #if defined(__cplusplus) +#include "lldb/lldb-defines.h" #include "lldb/Host/Mutex.h" #include "lldb/Host/Condition.h" #include diff --git a/include/lldb/Host/ProcessLauncher.h b/include/lldb/Host/ProcessLauncher.h new file mode 100644 index 000000000000..14685fd3c53a --- /dev/null +++ b/include/lldb/Host/ProcessLauncher.h @@ -0,0 +1,28 @@ +//===-- ProcessLauncher.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_ProcessLauncher_h_ +#define lldb_Host_ProcessLauncher_h_ + +namespace lldb_private +{ + +class ProcessLaunchInfo; +class Error; +class HostProcess; + +class ProcessLauncher +{ + public: + virtual ~ProcessLauncher() {} + virtual HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) = 0; +}; +} + +#endif diff --git a/include/lldb/Host/Socket.h b/include/lldb/Host/Socket.h index 0f3aa073001c..77069ae35f79 100644 --- a/include/lldb/Host/Socket.h +++ b/include/lldb/Host/Socket.h @@ -56,16 +56,16 @@ public: // Initialize a Tcp Socket object in listening mode. listen and accept are implemented // separately because the caller may wish to manipulate or query the socket after it is // initialized, but before entering a blocking accept. - static Error TcpListen(llvm::StringRef host_and_port, Socket *&socket, Predicate* predicate); - static Error TcpConnect(llvm::StringRef host_and_port, Socket *&socket); - static Error UdpConnect(llvm::StringRef host_and_port, Socket *&send_socket, Socket *&recv_socket); - static Error UnixDomainConnect(llvm::StringRef host_and_port, Socket *&socket); - static Error UnixDomainAccept(llvm::StringRef host_and_port, Socket *&socket); + static Error TcpListen(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket, Predicate* predicate); + static Error TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); + static Error UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket); + static Error UnixDomainConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); + static Error UnixDomainAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); // Blocks on a listening socket until a connection is received. This method assumes that // |this->m_socket| is a listening socket, created via either TcpListen() or via the native // constructor that takes a NativeSocket, which itself was created via a call to |listen()| - Error BlockingAccept(llvm::StringRef host_and_port, Socket *&socket); + Error BlockingAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); int GetOption (int level, int option_name, int &option_value); int SetOption (int level, int option_name, int option_value); diff --git a/include/lldb/Host/ThisThread.h b/include/lldb/Host/ThisThread.h new file mode 100644 index 000000000000..23acee9d3fc1 --- /dev/null +++ b/include/lldb/Host/ThisThread.h @@ -0,0 +1,40 @@ +//===-- ThisThread.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_ThisThread_h_ +#define lldb_Host_ThisThread_h_ + +#include "llvm/ADT/StringRef.h" + +#include + +namespace llvm +{ +template class SmallVectorImpl; +} + +namespace lldb_private +{ + +class ThisThread +{ + private: + ThisThread(); + + public: + // ThisThread common functions. + static void SetName(llvm::StringRef name, int max_length); + + // ThisThread platform-specific functions. + static void SetName(llvm::StringRef name); + static void GetName(llvm::SmallVectorImpl &name); +}; +} + +#endif diff --git a/include/lldb/Host/ThreadLauncher.h b/include/lldb/Host/ThreadLauncher.h new file mode 100644 index 000000000000..b4e4cae4b763 --- /dev/null +++ b/include/lldb/Host/ThreadLauncher.h @@ -0,0 +1,47 @@ +//===-- ThreadLauncher.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_ThreadLauncher_h_ +#define lldb_Host_ThreadLauncher_h_ + +#include "lldb/Core/Error.h" +#include "lldb/Host/HostThread.h" +#include "lldb/lldb-types.h" + +#include "llvm/ADT/StringRef.h" + +namespace lldb_private +{ + +class ThreadLauncher +{ + public: + static HostThread LaunchThread(llvm::StringRef name, + lldb::thread_func_t thread_function, + lldb::thread_arg_t thread_arg, + Error *error_ptr, + size_t min_stack_byte_size = 0); // Minimum stack size in bytes, set stack size to zero for default platform thread stack size + + struct HostThreadCreateInfo + { + std::string thread_name; + lldb::thread_func_t thread_fptr; + lldb::thread_arg_t thread_arg; + + HostThreadCreateInfo(const char *name, lldb::thread_func_t fptr, lldb::thread_arg_t arg) + : thread_name(name ? name : "") + , thread_fptr(fptr) + , thread_arg(arg) + { + } + }; +}; +} + +#endif diff --git a/include/lldb/Host/TimeValue.h b/include/lldb/Host/TimeValue.h index 1792d343a6a6..6de2bfd16a0a 100644 --- a/include/lldb/Host/TimeValue.h +++ b/include/lldb/Host/TimeValue.h @@ -31,6 +31,7 @@ public: static const uint64_t MicroSecPerSec = 1000000UL; static const uint64_t NanoSecPerSec = 1000000000UL; static const uint64_t NanoSecPerMicroSec = 1000U; + static const uint64_t NanoSecPerMilliSec = 1000000UL; //------------------------------------------------------------------ // Constructors and Destructors @@ -97,6 +98,15 @@ public: return (m_nano_seconds % NanoSecPerSec) / NanoSecPerMicroSec; } + /// Returns only the fractional portion of the TimeValue rounded down to the + /// nearest millisecond (divide by one million). + /// @brief Retrieve the milliseconds component; + uint32_t + milliseconds() const + { + return m_nano_seconds / NanoSecPerMilliSec; + } + protected: //------------------------------------------------------------------ // Classes that inherit from TimeValue can see and modify these diff --git a/include/lldb/Host/freebsd/HostInfoFreeBSD.h b/include/lldb/Host/freebsd/HostInfoFreeBSD.h index 1404a4b1525c..01dd99586f01 100644 --- a/include/lldb/Host/freebsd/HostInfoFreeBSD.h +++ b/include/lldb/Host/freebsd/HostInfoFreeBSD.h @@ -19,6 +19,7 @@ namespace lldb_private class HostInfoFreeBSD : public HostInfoPosix { public: + static uint32_t GetMaxThreadNameLength(); static bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update); static bool GetOSBuildString(std::string &s); static bool GetOSKernelDescription(std::string &s); diff --git a/include/lldb/Host/freebsd/HostThreadFreeBSD.h b/include/lldb/Host/freebsd/HostThreadFreeBSD.h new file mode 100644 index 000000000000..056957607af4 --- /dev/null +++ b/include/lldb/Host/freebsd/HostThreadFreeBSD.h @@ -0,0 +1,31 @@ +//===-- HostThreadFreeBSD.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_freebsd_HostThreadFreeBSD_h_ +#define lldb_Host_freebsd_HostThreadFreeBSD_h_ + +#include "lldb/Host/posix/HostThreadPosix.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallString.h" + +namespace lldb_private +{ + +class HostThreadFreeBSD : public HostThreadPosix +{ + public: + HostThreadFreeBSD(); + HostThreadFreeBSD(lldb::thread_t thread); + + static void GetName(lldb::tid_t tid, llvm::SmallVectorImpl &name); +}; +} + +#endif diff --git a/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h b/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h new file mode 100644 index 000000000000..4d326d71fa75 --- /dev/null +++ b/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h @@ -0,0 +1,108 @@ +//===-- ConnectionFileDescriptorPosix.h -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Host_posix_ConnectionFileDescriptorPosix_h_ +#define liblldb_Host_posix_ConnectionFileDescriptorPosix_h_ + +// C++ Includes +#include +#include + +#include "lldb/lldb-forward.h" + +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Connection.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Host/Pipe.h" +#include "lldb/Host/Predicate.h" +#include "lldb/Host/IOObject.h" + +namespace lldb_private +{ + +class Error; +class Socket; +class SocketAddress; + +class ConnectionFileDescriptor : public Connection +{ + public: + ConnectionFileDescriptor(bool child_processes_inherit = false); + + ConnectionFileDescriptor(int fd, bool owns_fd); + + virtual ~ConnectionFileDescriptor(); + + virtual bool IsConnected() const; + + virtual lldb::ConnectionStatus Connect(const char *s, Error *error_ptr); + + virtual lldb::ConnectionStatus Disconnect(Error *error_ptr); + + virtual size_t Read(void *dst, size_t dst_len, uint32_t timeout_usec, lldb::ConnectionStatus &status, Error *error_ptr); + + virtual size_t Write(const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr); + + lldb::ConnectionStatus BytesAvailable(uint32_t timeout_usec, Error *error_ptr); + + bool InterruptRead(); + + lldb::IOObjectSP + GetReadObject() + { + return m_read_sp; + } + const lldb::IOObjectSP + GetReadObject() const + { + return m_read_sp; + } + + uint16_t GetListeningPort(uint32_t timeout_sec); + + bool GetChildProcessesInherit() const; + void SetChildProcessesInherit(bool child_processes_inherit); + + protected: + void OpenCommandPipe(); + + void CloseCommandPipe(); + + lldb::ConnectionStatus SocketListen(const char *host_and_port, Error *error_ptr); + + lldb::ConnectionStatus ConnectTCP(const char *host_and_port, Error *error_ptr); + + lldb::ConnectionStatus ConnectUDP(const char *args, Error *error_ptr); + + lldb::ConnectionStatus NamedSocketConnect(const char *socket_name, Error *error_ptr); + + lldb::ConnectionStatus NamedSocketAccept(const char *socket_name, Error *error_ptr); + + lldb::IOObjectSP m_read_sp; + lldb::IOObjectSP m_write_sp; + + Predicate m_port_predicate; // Used when binding to port zero to wait for the thread + // that creates the socket, binds and listens to resolve + // the port number. + + Pipe m_pipe; + Mutex m_mutex; + std::atomic m_shutting_down; // This marks that we are shutting down so if we get woken up from + // BytesAvailable to disconnect, we won't try to read again. + bool m_waiting_for_accept; + bool m_child_processes_inherit; + + private: + DISALLOW_COPY_AND_ASSIGN(ConnectionFileDescriptor); +}; + +} // namespace lldb_private + +#endif // liblldb_ConnectionFileDescriptor_h_ diff --git a/include/lldb/Host/posix/HostInfoPosix.h b/include/lldb/Host/posix/HostInfoPosix.h index 6e0dcbe48021..9524a2a2481d 100644 --- a/include/lldb/Host/posix/HostInfoPosix.h +++ b/include/lldb/Host/posix/HostInfoPosix.h @@ -10,6 +10,7 @@ #ifndef lldb_Host_posix_HostInfoPosix_h_ #define lldb_Host_posix_HostInfoPosix_h_ +#include "lldb/Host/FileSpec.h" #include "lldb/Host/HostInfoBase.h" namespace lldb_private @@ -30,6 +31,8 @@ class HostInfoPosix : public HostInfoBase static uint32_t GetEffectiveUserID(); static uint32_t GetEffectiveGroupID(); + static FileSpec GetDefaultShell(); + protected: static bool ComputeSupportExeDirectory(FileSpec &file_spec); static bool ComputeHeaderDirectory(FileSpec &file_spec); diff --git a/include/lldb/Host/posix/HostProcessPosix.h b/include/lldb/Host/posix/HostProcessPosix.h index aa003ee4845e..8c1b0599e114 100644 --- a/include/lldb/Host/posix/HostProcessPosix.h +++ b/include/lldb/Host/posix/HostProcessPosix.h @@ -12,34 +12,30 @@ #include "lldb/lldb-types.h" #include "lldb/Core/Error.h" -#include "lldb/Target/ProcessLaunchInfo.h" +#include "lldb/Host/HostNativeProcessBase.h" namespace lldb_private { class FileSpec; -class HostProcessPosix +class HostProcessPosix : public HostNativeProcessBase { public: - static const lldb::pid_t kInvalidProcessId; - HostProcessPosix(); - ~HostProcessPosix(); - - Error Signal(int signo) const; - static Error Signal(lldb::pid_t pid, int signo); + HostProcessPosix(lldb::process_t process); + virtual ~HostProcessPosix(); - Error Create(lldb::pid_t pid); - Error Terminate(int signo); - Error GetMainModule(FileSpec &file_spec) const; + virtual Error Signal(int signo) const; + static Error Signal(lldb::process_t process, int signo); - lldb::pid_t GetProcessId() const; - bool IsRunning() const; + virtual Error Terminate(); + virtual Error GetMainModule(FileSpec &file_spec) const; - private: + virtual lldb::pid_t GetProcessId() const; + virtual bool IsRunning() const; - lldb::pid_t m_pid; + virtual HostThread StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals); }; } diff --git a/include/lldb/Host/posix/HostThreadPosix.h b/include/lldb/Host/posix/HostThreadPosix.h new file mode 100644 index 000000000000..e0eaedf73be2 --- /dev/null +++ b/include/lldb/Host/posix/HostThreadPosix.h @@ -0,0 +1,34 @@ +//===-- HostThreadPosix.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_posix_HostThreadPosix_h_ +#define lldb_Host_posix_HostThreadPosix_h_ + +#include "lldb/Host/HostNativeThreadBase.h" + +namespace lldb_private +{ + +class HostThreadPosix : public HostNativeThreadBase +{ + DISALLOW_COPY_AND_ASSIGN(HostThreadPosix); + + public: + HostThreadPosix(); + HostThreadPosix(lldb::thread_t thread); + virtual ~HostThreadPosix(); + + virtual Error Join(lldb::thread_result_t *result); + virtual Error Cancel(); + + Error Detach(); +}; +} + +#endif diff --git a/include/lldb/Host/posix/PipePosix.h b/include/lldb/Host/posix/PipePosix.h new file mode 100644 index 000000000000..0ab3ff7f6775 --- /dev/null +++ b/include/lldb/Host/posix/PipePosix.h @@ -0,0 +1,81 @@ +//===-- PipePosix.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Host_posix_PipePosix_h_ +#define liblldb_Host_posix_PipePosix_h_ +#if defined(__cplusplus) + +#include "lldb/Host/PipeBase.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class PipePosix PipePosix .h "lldb/Host/posix/PipePosix.h" +/// @brief A posix-based implementation of Pipe, a class that abtracts +/// unix style pipes. +/// +/// A class that abstracts the LLDB core from host pipe functionality. +//---------------------------------------------------------------------- +class PipePosix : public PipeBase +{ +public: + static int kInvalidDescriptor; + + PipePosix(); + + ~PipePosix() override; + + Error + CreateNew(bool child_process_inherit) override; + Error + CreateNew(llvm::StringRef name, bool child_process_inherit) override; + Error + OpenAsReader(llvm::StringRef name, bool child_process_inherit) override; + Error + OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) override; + + bool + CanRead() const override; + bool + CanWrite() const override; + + int + GetReadFileDescriptor() const override; + int + GetWriteFileDescriptor() const override; + int + ReleaseReadFileDescriptor() override; + int + ReleaseWriteFileDescriptor() override; + + // Close both descriptors + void + Close() override; + + Error + Delete(llvm::StringRef name) override; + + Error + Write(const void *buf, size_t size, size_t &bytes_written) override; + Error + ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read) override; + +private: + void + CloseReadFileDescriptor(); + void + CloseWriteFileDescriptor(); + + int m_fds[2]; +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_Host_posix_PipePosix_h_ diff --git a/include/lldb/Host/posix/ProcessLauncherPosix.h b/include/lldb/Host/posix/ProcessLauncherPosix.h new file mode 100644 index 000000000000..c0e2a36e4e5e --- /dev/null +++ b/include/lldb/Host/posix/ProcessLauncherPosix.h @@ -0,0 +1,25 @@ +//===-- ProcessLauncherPosix.h ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_posix_ProcessLauncherPosix_h_ +#define lldb_Host_posix_ProcessLauncherPosix_h_ + +#include "lldb/Host/ProcessLauncher.h" + +namespace lldb_private +{ + +class ProcessLauncherPosix : public ProcessLauncher +{ + public: + virtual HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error); +}; +} + +#endif diff --git a/include/lldb/Interpreter/Args.h b/include/lldb/Interpreter/Args.h index 06617f1e5926..1071bd6fd047 100644 --- a/include/lldb/Interpreter/Args.h +++ b/include/lldb/Interpreter/Args.h @@ -394,7 +394,9 @@ public: static bool StringToBoolean (const char *s, bool fail_value, bool *success_ptr); - + + static char StringToChar(const char *s, char fail_value, bool *success_ptr); + static int64_t StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error); diff --git a/include/lldb/Interpreter/CommandInterpreter.h b/include/lldb/Interpreter/CommandInterpreter.h index c33d71a6dbbb..baaa271a4285 100644 --- a/include/lldb/Interpreter/CommandInterpreter.h +++ b/include/lldb/Interpreter/CommandInterpreter.h @@ -28,12 +28,179 @@ namespace lldb_private { +class CommandInterpreterRunOptions +{ +public: + //------------------------------------------------------------------ + /// Construct a CommandInterpreterRunOptions object. + /// This class is used to control all the instances where we run multiple commands, e.g. + /// HandleCommands, HandleCommandsFromFile, RunCommandInterpreter. + /// The meanings of the options in this object are: + /// + /// @param[in] stop_on_continue + /// If \b true execution will end on the first command that causes the process in the + /// execution context to continue. If \false, we won't check the execution status. + /// @param[in] stop_on_error + /// If \b true execution will end on the first command that causes an error. + /// @param[in] stop_on_crash + /// If \b true when a command causes the target to run, and the end of the run is a + /// signal or exception, stop executing the commands. + /// @param[in] echo_commands + /// If \b true echo the command before executing it. If \false, execute silently. + /// @param[in] print_results + /// If \b true print the results of the command after executing it. If \false, execute silently. + /// @param[in] add_to_history + /// If \b true add the commands to the command history. If \false, don't add them. + //------------------------------------------------------------------ + CommandInterpreterRunOptions (LazyBool stop_on_continue, + LazyBool stop_on_error, + LazyBool stop_on_crash, + LazyBool echo_commands, + LazyBool print_results, + LazyBool add_to_history) : + m_stop_on_continue(stop_on_continue), + m_stop_on_error(stop_on_error), + m_stop_on_crash(stop_on_crash), + m_echo_commands(echo_commands), + m_print_results(print_results), + m_add_to_history(add_to_history) + {} + + CommandInterpreterRunOptions () : + m_stop_on_continue(eLazyBoolCalculate), + m_stop_on_error(eLazyBoolCalculate), + m_stop_on_crash(eLazyBoolCalculate), + m_echo_commands(eLazyBoolCalculate), + m_print_results(eLazyBoolCalculate), + m_add_to_history(eLazyBoolCalculate) + {} + + void + SetSilent (bool silent) + { + LazyBool value = silent ? eLazyBoolNo : eLazyBoolYes; + + m_echo_commands = value; + m_print_results = value; + m_add_to_history = value; + } + // These return the default behaviors if the behavior is not eLazyBoolCalculate. + // But I've also left the ivars public since for different ways of running the + // interpreter you might want to force different defaults... In that case, just grab + // the LazyBool ivars directly and do what you want with eLazyBoolCalculate. + bool + GetStopOnContinue () const + { + return DefaultToNo (m_stop_on_continue); + } + + void + SetStopOnContinue (bool stop_on_continue) + { + m_stop_on_continue = stop_on_continue ? eLazyBoolYes : eLazyBoolNo; + } + + bool + GetStopOnError () const + { + return DefaultToNo (m_stop_on_continue); + } + + void + SetStopOnError (bool stop_on_error) + { + m_stop_on_error = stop_on_error ? eLazyBoolYes : eLazyBoolNo; + } + + bool + GetStopOnCrash () const + { + return DefaultToNo (m_stop_on_crash); + } + + void + SetStopOnCrash (bool stop_on_crash) + { + m_stop_on_crash = stop_on_crash ? eLazyBoolYes : eLazyBoolNo; + } + + bool + GetEchoCommands () const + { + return DefaultToYes (m_echo_commands); + } + + void + SetEchoCommands (bool echo_commands) + { + m_echo_commands = echo_commands ? eLazyBoolYes : eLazyBoolNo; + } + + bool + GetPrintResults () const + { + return DefaultToYes (m_print_results); + } + + void + SetPrintResults (bool print_results) + { + m_print_results = print_results ? eLazyBoolYes : eLazyBoolNo; + } + + bool + GetAddToHistory () const + { + return DefaultToYes (m_add_to_history); + } + + void + SetAddToHistory (bool add_to_history) + { + m_add_to_history = add_to_history ? eLazyBoolYes : eLazyBoolNo; + } + + LazyBool m_stop_on_continue; + LazyBool m_stop_on_error; + LazyBool m_stop_on_crash; + LazyBool m_echo_commands; + LazyBool m_print_results; + LazyBool m_add_to_history; + + private: + static bool + DefaultToYes (LazyBool flag) + { + switch (flag) + { + case eLazyBoolNo: + return false; + default: + return true; + } + } + + static bool + DefaultToNo (LazyBool flag) + { + switch (flag) + { + case eLazyBoolYes: + return true; + default: + return false; + } + } +}; + class CommandInterpreter : public Broadcaster, public Properties, public IOHandlerDelegate { public: + + typedef std::map OptionArgMap; enum @@ -115,6 +282,10 @@ public: AddAlias (const char *alias_name, lldb::CommandObjectSP& command_obj_sp); + // Remove a command if it is removable (python or regex command) + bool + RemoveCommand (const char *cmd); + bool RemoveAlias (const char *alias_name); @@ -168,27 +339,17 @@ public: /// @param[in/out] context /// The execution context in which to run the commands. Can be NULL in which case the default /// context will be used. - /// @param[in] stop_on_continue - /// If \b true execution will end on the first command that causes the process in the - /// execution context to continue. If \false, we won't check the execution status. - /// @param[in] stop_on_error - /// If \b true execution will end on the first command that causes an error. - /// @param[in] echo_commands - /// If \b true echo the command before executing it. If \false, execute silently. - /// @param[in] print_results - /// If \b true print the results of the command after executing it. If \false, execute silently. - /// @param[out] result + /// @param[in] options + /// This object holds the options used to control when to stop, whether to execute commands, + /// etc. + /// @param[out] result /// This is marked as succeeding with no output if all commands execute safely, /// and failed with some explanation if we aborted executing the commands at some point. //------------------------------------------------------------------ void HandleCommands (const StringList &commands, - ExecutionContext *context, - bool stop_on_continue, - bool stop_on_error, - bool echo_commands, - bool print_results, - LazyBool add_to_history, + ExecutionContext *context, + CommandInterpreterRunOptions &options, CommandReturnObject &result); //------------------------------------------------------------------ @@ -199,27 +360,17 @@ public: /// @param[in/out] context /// The execution context in which to run the commands. Can be NULL in which case the default /// context will be used. - /// @param[in] stop_on_continue - /// If \b true execution will end on the first command that causes the process in the - /// execution context to continue. If \false, we won't check the execution status. - /// @param[in] stop_on_error - /// If \b true execution will end on the first command that causes an error. - /// @param[in] echo_commands - /// If \b true echo the command before executing it. If \false, execute silently. - /// @param[in] print_results - /// If \b true print the results of the command after executing it. If \false, execute silently. - /// @param[out] result + /// @param[in] options + /// This object holds the options used to control when to stop, whether to execute commands, + /// etc. + /// @param[out] result /// This is marked as succeeding with no output if all commands execute safely, /// and failed with some explanation if we aborted executing the commands at some point. //------------------------------------------------------------------ void HandleCommandsFromFile (FileSpec &file, - ExecutionContext *context, - LazyBool stop_on_continue, - LazyBool stop_on_error, - LazyBool echo_commands, - LazyBool print_results, - LazyBool add_to_history, + ExecutionContext *context, + CommandInterpreterRunOptions &options, CommandReturnObject &result); CommandObject * @@ -442,8 +593,8 @@ public: void RunCommandInterpreter (bool auto_handle_events, - bool spawn_thread); - + bool spawn_thread, + CommandInterpreterRunOptions &options); void GetLLDBCommandsFromIOHandler (const char *prompt, IOHandlerDelegate &delegate, @@ -467,6 +618,27 @@ public: bool GetStopCmdSourceOnError () const; + + uint32_t + GetNumErrors() const + { + return m_num_errors; + } + + bool + GetQuitRequested () const + { + return m_quit_requested; + } + + lldb::IOHandlerSP + GetIOHandler(bool force_create = false, CommandInterpreterRunOptions *options = NULL); + + bool + GetStoppedForCrash () const + { + return m_stopped_for_crash; + } protected: friend class Debugger; @@ -522,6 +694,9 @@ private: ChildrenTruncatedWarningStatus m_truncation_warning; // Whether we truncated children and whether the user has been told uint32_t m_command_source_depth; std::vector m_command_source_flags; + uint32_t m_num_errors; + bool m_quit_requested; + bool m_stopped_for_crash; }; diff --git a/include/lldb/Interpreter/CommandObject.h b/include/lldb/Interpreter/CommandObject.h index 7bdf55a393d7..bace3264dafa 100644 --- a/include/lldb/Interpreter/CommandObject.h +++ b/include/lldb/Interpreter/CommandObject.h @@ -525,6 +525,11 @@ protected: return "invalid frame, no registers"; } + // This is for use in the command interpreter, when you either want the selected target, or if no target + // is present you want to prime the dummy target with entities that will be copied over to new targets. + Target *GetSelectedOrDummyTarget(bool prefer_dummy = false); + Target *GetDummyTarget(); + //------------------------------------------------------------------ /// Check the command to make sure anything required by this /// command is available. @@ -605,7 +610,7 @@ public: virtual bool Execute (const char *args_string, CommandReturnObject &result); - + protected: virtual bool DoExecute (const char *command, CommandReturnObject &result) = 0; diff --git a/include/lldb/Interpreter/CommandObjectRegexCommand.h b/include/lldb/Interpreter/CommandObjectRegexCommand.h index 8855680d5f8b..d86544638776 100644 --- a/include/lldb/Interpreter/CommandObjectRegexCommand.h +++ b/include/lldb/Interpreter/CommandObjectRegexCommand.h @@ -34,11 +34,15 @@ public: const char *help, const char *syntax, uint32_t max_matches, - uint32_t completion_type_mask = 0); + uint32_t completion_type_mask, + bool is_removable); virtual ~CommandObjectRegexCommand (); + bool + IsRemovable () const override { return m_is_removable; } + bool AddRegexCommand (const char *re_cstr, const char *command_cstr); @@ -48,18 +52,18 @@ public: return !m_entries.empty(); } - virtual int + int HandleCompletion (Args &input, int &cursor_index, int &cursor_char_position, int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches); + StringList &matches) override; protected: - virtual bool - DoExecute (const char *command, CommandReturnObject &result); + bool + DoExecute (const char *command, CommandReturnObject &result) override; struct Entry { @@ -71,6 +75,7 @@ protected: const uint32_t m_max_matches; const uint32_t m_completion_type_mask; EntryCollection m_entries; + bool m_is_removable; private: DISALLOW_COPY_AND_ASSIGN (CommandObjectRegexCommand); diff --git a/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h b/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h index c09528f9f514..5cce126f89bf 100644 --- a/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h +++ b/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h @@ -59,7 +59,8 @@ public: ptr_depth != 0 || use_synth == false || be_raw == true || - ignore_cap == true; + ignore_cap == true || + run_validator == true; } DumpValueObjectOptions @@ -67,17 +68,19 @@ public: lldb::Format format = lldb::eFormatDefault, lldb::TypeSummaryImplSP summary_sp = lldb::TypeSummaryImplSP()); - bool show_types; + bool show_types : 1, + show_location : 1, + flat_output : 1, + use_objc : 1, + use_synth : 1, + be_raw : 1, + ignore_cap : 1, + run_validator : 1; + uint32_t no_summary_depth; - bool show_location; - bool flat_output; - bool use_objc; uint32_t max_depth; uint32_t ptr_depth; lldb::DynamicValueType use_dynamic; - bool use_synth; - bool be_raw; - bool ignore_cap; }; } // namespace lldb_private diff --git a/include/lldb/Interpreter/OptionValue.h b/include/lldb/Interpreter/OptionValue.h index 33e7fc5f818b..0e8f23453a8a 100644 --- a/include/lldb/Interpreter/OptionValue.h +++ b/include/lldb/Interpreter/OptionValue.h @@ -26,12 +26,14 @@ namespace lldb_private { class OptionValue { public: - typedef enum { + typedef enum + { eTypeInvalid = 0, eTypeArch, eTypeArgs, eTypeArray, eTypeBoolean, + eTypeChar, eTypeDictionary, eTypeEnum, eTypeFileSpec, @@ -41,11 +43,11 @@ namespace lldb_private { eTypeProperties, eTypeRegex, eTypeSInt64, - eTypeString, + eTypeString, eTypeUInt64, eTypeUUID } Type; - + enum { eDumpOptionName = (1u << 0), eDumpOptionType = (1u << 1), @@ -58,11 +60,15 @@ namespace lldb_private { OptionValue () : + m_callback (nullptr), + m_baton(nullptr), m_value_was_set (false) { } OptionValue (const OptionValue &rhs) : + m_callback (rhs.m_callback), + m_baton (rhs.m_baton), m_value_was_set (rhs.m_value_was_set) { } @@ -173,6 +179,7 @@ namespace lldb_private { case 1u << eTypeArgs: return eTypeArgs; case 1u << eTypeArray: return eTypeArray; case 1u << eTypeBoolean: return eTypeBoolean; + case 1u << eTypeChar: return eTypeChar; case 1u << eTypeDictionary: return eTypeDictionary; case 1u << eTypeEnum: return eTypeEnum; case 1u << eTypeFileSpec: return eTypeFileSpec; @@ -221,10 +228,16 @@ namespace lldb_private { OptionValueBoolean * GetAsBoolean (); - + + OptionValueChar * + GetAsChar (); + const OptionValueBoolean * GetAsBoolean () const; - + + const OptionValueChar * + GetAsChar () const; + OptionValueDictionary * GetAsDictionary (); @@ -302,7 +315,11 @@ namespace lldb_private { bool SetBooleanValue (bool new_value); - + + char GetCharValue(char fail_value) const; + + char SetCharValue(char new_value); + int64_t GetEnumerationValue (int64_t fail_value = -1) const; @@ -368,8 +385,26 @@ namespace lldb_private { { m_parent_wp = parent_sp; } + + void + SetValueChangedCallback (OptionValueChangedCallback callback, + void *baton) + { + assert (m_callback == NULL); + m_callback = callback; + m_baton = baton; + } + + void + NotifyValueChanged () + { + if (m_callback) + m_callback (m_baton, this); + } protected: lldb::OptionValueWP m_parent_wp; + OptionValueChangedCallback m_callback; + void *m_baton; bool m_value_was_set; // This can be used to see if a value has been set // by a call to SetValueFromCString(). It is often // handy to know if an option value was set from diff --git a/include/lldb/Interpreter/OptionValueChar.h b/include/lldb/Interpreter/OptionValueChar.h new file mode 100644 index 000000000000..55f4b63538ea --- /dev/null +++ b/include/lldb/Interpreter/OptionValueChar.h @@ -0,0 +1,113 @@ +//===-- OptionValueBoolean.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_OptionValueChar_h_ +#define liblldb_OptionValueChar_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValueChar : public OptionValue +{ +public: + OptionValueChar (char value) : + OptionValue(), + m_current_value (value), + m_default_value (value) + { + } + OptionValueChar (char current_value, + char default_value) : + OptionValue(), + m_current_value (current_value), + m_default_value (default_value) + { + } + + virtual + ~OptionValueChar() + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () const + { + return eTypeChar; + } + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + + virtual Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () + { + m_current_value = m_default_value; + m_value_was_set = false; + return true; + } + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + const char & + operator = (char c) + { + m_current_value = c; + return m_current_value; + } + + char + GetCurrentValue() const + { + return m_current_value; + } + + char + GetDefaultValue() const + { + return m_default_value; + } + + void + SetCurrentValue (char value) + { + m_current_value = value; + } + + void + SetDefaultValue (char value) + { + m_default_value = value; + } + + virtual lldb::OptionValueSP + DeepCopy () const; + +protected: + char m_current_value; + char m_default_value; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueChar_h_ diff --git a/include/lldb/Interpreter/OptionValueProperties.h b/include/lldb/Interpreter/OptionValueProperties.h index 0024f20e2ff6..a67ea5d66e54 100644 --- a/include/lldb/Interpreter/OptionValueProperties.h +++ b/include/lldb/Interpreter/OptionValueProperties.h @@ -243,8 +243,20 @@ public: GetSubProperty (const ExecutionContext *exe_ctx, const ConstString &name); + void + SetValueChangedCallback (uint32_t property_idx, + OptionValueChangedCallback callback, + void *baton); protected: - + + Property * + ProtectedGetPropertyAtIndex (uint32_t idx) + { + if (idx < m_properties.size()) + return &m_properties[idx]; + return NULL; + } + const Property * ProtectedGetPropertyAtIndex (uint32_t idx) const { diff --git a/include/lldb/Interpreter/OptionValues.h b/include/lldb/Interpreter/OptionValues.h index 41b9d2e351f4..c66fc4dab2f6 100644 --- a/include/lldb/Interpreter/OptionValues.h +++ b/include/lldb/Interpreter/OptionValues.h @@ -15,6 +15,7 @@ #include "lldb/Interpreter/OptionValueArgs.h" #include "lldb/Interpreter/OptionValueArray.h" #include "lldb/Interpreter/OptionValueBoolean.h" +#include "lldb/Interpreter/OptionValueChar.h" #include "lldb/Interpreter/OptionValueDictionary.h" #include "lldb/Interpreter/OptionValueEnumeration.h" #include "lldb/Interpreter/OptionValueFileSpec.h" diff --git a/include/lldb/Interpreter/Property.h b/include/lldb/Interpreter/Property.h index b192758cbc41..cb4c827ded06 100644 --- a/include/lldb/Interpreter/Property.h +++ b/include/lldb/Interpreter/Property.h @@ -29,7 +29,7 @@ namespace lldb_private { { const char *name; OptionValue::Type type; - bool global; + bool global; // false == this setting is a global setting by default uintptr_t default_uint_value; const char *default_cstr_value; OptionEnumValueElement *enum_values; @@ -97,6 +97,9 @@ namespace lldb_private { uint32_t output_width, bool display_qualified_name) const; + void + SetValueChangedCallback (OptionValueChangedCallback callback, void *baton); + protected: ConstString m_name; ConstString m_description; diff --git a/include/lldb/Interpreter/ScriptInterpreter.h b/include/lldb/Interpreter/ScriptInterpreter.h index 5a8322f8eb4f..35ba9491ded0 100644 --- a/include/lldb/Interpreter/ScriptInterpreter.h +++ b/include/lldb/Interpreter/ScriptInterpreter.h @@ -98,12 +98,19 @@ public: void *session_dictionary, const lldb::ValueObjectSP& valobj_sp, void** pyfunct_wrapper, + const lldb::TypeSummaryOptionsSP& options, std::string& retval); typedef void* (*SWIGPythonCreateSyntheticProvider) (const char *python_class_name, const char *session_dictionary_name, const lldb::ValueObjectSP& valobj_sp); + typedef void* (*SWIGPythonCreateScriptedThreadPlan) (const char *python_class_name, + const char *session_dictionary_name, + const lldb::ThreadPlanSP& thread_plan_sp); + + typedef bool (*SWIGPythonCallThreadPlan) (void *implementor, const char *method_name, Event *event_sp, bool &got_error); + typedef void* (*SWIGPythonCreateOSPlugin) (const char *python_class_name, const char *session_dictionary_name, const lldb::ProcessSP& process_sp); @@ -115,13 +122,14 @@ public: typedef lldb::ValueObjectSP (*SWIGPythonGetValueObjectSPFromSBValue) (void* data); typedef bool (*SWIGPythonUpdateSynthProviderInstance) (void* data); typedef bool (*SWIGPythonMightHaveChildrenSynthProviderInstance) (void* data); - + typedef void* (*SWIGPythonGetValueSynthProviderInstance) (void *implementor); typedef bool (*SWIGPythonCallCommand) (const char *python_function_name, const char *session_dictionary_name, lldb::DebuggerSP& debugger, const char* args, - lldb_private::CommandReturnObject& cmd_retobj); + lldb_private::CommandReturnObject& cmd_retobj, + lldb::ExecutionContextRefSP exe_ctx_ref_sp); typedef bool (*SWIGPythonCallModuleInit) (const char *python_module_name, const char *session_dictionary_name, @@ -145,6 +153,11 @@ public: const char* session_dictionary_name, lldb::StackFrameSP& frame, std::string& output); + + typedef bool (*SWIGPythonScriptKeyword_Value) (const char* python_function_name, + const char* session_dictionary_name, + lldb::ValueObjectSP& value, + std::string& output); typedef void* (*SWIGPython_GetDynamicSetting) (void* module, const char* setting, @@ -347,6 +360,39 @@ public: return lldb::ScriptInterpreterObjectSP(); } + virtual lldb::ScriptInterpreterObjectSP + CreateScriptedThreadPlan (const char *class_name, + lldb::ThreadPlanSP thread_plan_sp) + { + return lldb::ScriptInterpreterObjectSP(); + } + + virtual bool + ScriptedThreadPlanExplainsStop (lldb::ScriptInterpreterObjectSP implementor_sp, + Event *event, + bool &script_error) + { + script_error = true; + return true; + } + + virtual bool + ScriptedThreadPlanShouldStop (lldb::ScriptInterpreterObjectSP implementor_sp, + Event *event, + bool &script_error) + { + script_error = true; + return true; + } + + virtual lldb::StateType + ScriptedThreadPlanGetRunState (lldb::ScriptInterpreterObjectSP implementor_sp, + bool &script_error) + { + script_error = true; + return lldb::eStateStepping; + } + virtual lldb::ScriptInterpreterObjectSP LoadPluginModule (const FileSpec& file_spec, lldb_private::Error& error) @@ -417,6 +463,7 @@ public: GetScriptedSummary (const char *function_name, lldb::ValueObjectSP valobj, lldb::ScriptInterpreterObjectSP& callee_wrapper_sp, + const TypeSummaryOptions& options, std::string& retval) { return false; @@ -458,12 +505,19 @@ public: return true; } + virtual lldb::ValueObjectSP + GetSyntheticValue (const lldb::ScriptInterpreterObjectSP& implementor) + { + return nullptr; + } + virtual bool RunScriptBasedCommand (const char* impl_function, const char* args, ScriptedCommandSynchronicity synchronicity, lldb_private::CommandReturnObject& cmd_retobj, - Error& error) + Error& error, + const lldb_private::ExecutionContext& exe_ctx) { return false; } @@ -508,6 +562,16 @@ public: return false; } + virtual bool + RunScriptFormatKeyword (const char* impl_function, + ValueObject* value, + std::string& output, + Error& error) + { + error.SetErrorString("unimplemented"); + return false; + } + virtual bool GetDocumentationForItem (const char* item, std::string& dest) { @@ -566,6 +630,7 @@ public: SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, SWIGPythonUpdateSynthProviderInstance swig_update_provider, SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, + SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, SWIGPythonCallCommand swig_call_command, SWIGPythonCallModuleInit swig_call_module_init, SWIGPythonCreateOSPlugin swig_create_os_plugin, @@ -573,7 +638,10 @@ public: SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, - SWIGPython_GetDynamicSetting swig_plugin_get); + SWIGPythonScriptKeyword_Value swig_run_script_keyword_value, + SWIGPython_GetDynamicSetting swig_plugin_get, + SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script, + SWIGPythonCallThreadPlan swig_call_thread_plan); virtual void ResetOutputFileHandle (FILE *new_fh) { } //By default, do nothing. diff --git a/include/lldb/Interpreter/ScriptInterpreterPython.h b/include/lldb/Interpreter/ScriptInterpreterPython.h index 14a62d67fde6..edcc4c44facb 100644 --- a/include/lldb/Interpreter/ScriptInterpreterPython.h +++ b/include/lldb/Interpreter/ScriptInterpreterPython.h @@ -80,6 +80,22 @@ public: lldb::ScriptInterpreterObjectSP CreateSyntheticScriptedProvider (const char *class_name, lldb::ValueObjectSP valobj); + + lldb::ScriptInterpreterObjectSP + virtual CreateScriptedThreadPlan (const char *class_name, + lldb::ThreadPlanSP thread_plan); + + virtual bool + ScriptedThreadPlanExplainsStop (lldb::ScriptInterpreterObjectSP implementor_sp, + Event *event, + bool &script_error); + virtual bool + ScriptedThreadPlanShouldStop (lldb::ScriptInterpreterObjectSP implementor_sp, + Event *event, + bool &script_error); + virtual lldb::StateType + ScriptedThreadPlanGetRunState (lldb::ScriptInterpreterObjectSP implementor_sp, + bool &script_error); virtual lldb::ScriptInterpreterObjectSP OSPlugin_CreatePluginObject (const char *class_name, @@ -125,12 +141,16 @@ public: virtual bool MightHaveChildrenSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor); + virtual lldb::ValueObjectSP + GetSyntheticValue (const lldb::ScriptInterpreterObjectSP& implementor); + virtual bool RunScriptBasedCommand(const char* impl_function, const char* args, ScriptedCommandSynchronicity synchronicity, lldb_private::CommandReturnObject& cmd_retobj, - Error& error); + Error& error, + const lldb_private::ExecutionContext& exe_ctx); Error GenerateFunction(const char *signature, const StringList &input); @@ -170,6 +190,7 @@ public: GetScriptedSummary (const char *function_name, lldb::ValueObjectSP valobj, lldb::ScriptInterpreterObjectSP& callee_wrapper_sp, + const TypeSummaryOptions& options, std::string& retval); virtual void @@ -211,6 +232,12 @@ public: std::string& output, Error& error); + virtual bool + RunScriptFormatKeyword (const char* impl_function, + ValueObject* value, + std::string& output, + Error& error); + virtual bool LoadScriptingModule (const char* filename, bool can_reload, @@ -268,6 +295,7 @@ public: SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, SWIGPythonUpdateSynthProviderInstance swig_update_provider, SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, + SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, SWIGPythonCallCommand swig_call_command, SWIGPythonCallModuleInit swig_call_module_init, SWIGPythonCreateOSPlugin swig_create_os_plugin, @@ -275,7 +303,10 @@ public: SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, - SWIGPython_GetDynamicSetting swig_plugin_get); + SWIGPythonScriptKeyword_Value swig_run_script_keyword_value, + SWIGPython_GetDynamicSetting swig_plugin_get, + SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script, + SWIGPythonCallThreadPlan swig_call_thread_plan); const char * GetDictionaryName () diff --git a/include/lldb/Symbol/ClangASTContext.h b/include/lldb/Symbol/ClangASTContext.h index 2bb911c6e566..a9096fe66151 100644 --- a/include/lldb/Symbol/ClangASTContext.h +++ b/include/lldb/Symbol/ClangASTContext.h @@ -14,17 +14,21 @@ #include // C++ Includes +#include #include #include +#include // Other libraries and framework includes #include "llvm/ADT/SmallVector.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/TemplateBase.h" // Project includes #include "lldb/lldb-enumerations.h" #include "lldb/Core/ClangForward.h" +#include "lldb/Core/ConstString.h" #include "lldb/Symbol/ClangASTType.h" namespace lldb_private { @@ -208,11 +212,47 @@ public: ClangASTType type2, bool ignore_qualifiers = false); - ClangASTType + static ClangASTType + GetTypeForDecl (clang::NamedDecl *decl); + + static ClangASTType GetTypeForDecl (clang::TagDecl *decl); - ClangASTType + static ClangASTType GetTypeForDecl (clang::ObjCInterfaceDecl *objc_decl); + + template + ClangASTType + GetTypeForIdentifier (const ConstString &type_name) + { + ClangASTType clang_type; + + if (type_name.GetLength()) + { + clang::ASTContext *ast = getASTContext(); + if (ast) + { + clang::IdentifierInfo &myIdent = ast->Idents.get(type_name.GetCString()); + clang::DeclarationName myName = ast->DeclarationNames.getIdentifier(&myIdent); + + clang::DeclContext::lookup_const_result result = ast->getTranslationUnitDecl()->lookup(myName); + + if (!result.empty()) + { + clang::NamedDecl *named_decl = result[0]; + if (const RecordDeclType *record_decl = llvm::dyn_cast(named_decl)) + clang_type.SetClangType(ast, clang::QualType(record_decl->getTypeForDecl(), 0)); + } + } + } + + return clang_type; + } + + ClangASTType + GetOrCreateStructForIdentifier (const ConstString &type_name, + const std::initializer_list< std::pair < const char *, ClangASTType > >& type_fields, + bool packed = false); //------------------------------------------------------------------ // Structure, Unions, Classes diff --git a/include/lldb/Symbol/ClangASTType.h b/include/lldb/Symbol/ClangASTType.h index 4dd17031e568..ef23a8be645b 100644 --- a/include/lldb/Symbol/ClangASTType.h +++ b/include/lldb/Symbol/ClangASTType.h @@ -30,32 +30,6 @@ namespace lldb_private { class ClangASTType { public: - enum { - eTypeHasChildren = (1u << 0), - eTypeHasValue = (1u << 1), - eTypeIsArray = (1u << 2), - eTypeIsBlock = (1u << 3), - eTypeIsBuiltIn = (1u << 4), - eTypeIsClass = (1u << 5), - eTypeIsCPlusPlus = (1u << 6), - eTypeIsEnumeration = (1u << 7), - eTypeIsFuncPrototype = (1u << 8), - eTypeIsMember = (1u << 9), - eTypeIsObjC = (1u << 10), - eTypeIsPointer = (1u << 11), - eTypeIsReference = (1u << 12), - eTypeIsStructUnion = (1u << 13), - eTypeIsTemplate = (1u << 14), - eTypeIsTypedef = (1u << 15), - eTypeIsVector = (1u << 16), - eTypeIsScalar = (1u << 17), - eTypeIsInteger = (1u << 18), - eTypeIsFloat = (1u << 19), - eTypeIsComplex = (1u << 20), - eTypeIsSigned = (1u << 21) - }; - - //---------------------------------------------------------------------- // Constructors and Destructors //---------------------------------------------------------------------- @@ -162,7 +136,7 @@ public: GetNumberOfFunctionArguments () const; ClangASTType - GetFunctionArgumentAtIndex (const size_t index); + GetFunctionArgumentAtIndex (const size_t index) const; bool IsVariadicFunctionType () const; @@ -329,11 +303,17 @@ public: GetFunctionArgumentCount () const; ClangASTType - GetFunctionArgumentTypeAtIndex (size_t idx); + GetFunctionArgumentTypeAtIndex (size_t idx) const; ClangASTType GetFunctionReturnType () const; + size_t + GetNumMemberFunctions () const; + + TypeMemberFunctionImpl + GetMemberFunctionAtIndex (size_t idx); + ClangASTType GetLValueReferenceType () const; @@ -475,6 +455,9 @@ public: void BuildIndirectFields (); + void + SetIsPacked (); + clang::VarDecl * AddVariableToRecordType (const char *name, const ClangASTType &var_type, diff --git a/include/lldb/Symbol/ClangExternalASTSourceCommon.h b/include/lldb/Symbol/ClangExternalASTSourceCommon.h index 20c4b4354367..17650f7f14fd 100644 --- a/include/lldb/Symbol/ClangExternalASTSourceCommon.h +++ b/include/lldb/Symbol/ClangExternalASTSourceCommon.h @@ -169,18 +169,16 @@ public: ClangExternalASTSourceCommon(); ~ClangExternalASTSourceCommon(); - virtual ClangASTMetadata *GetMetadata(const void *object); - virtual void SetMetadata(const void *object, ClangASTMetadata &metadata); - virtual bool HasMetadata(const void *object); -private: + ClangASTMetadata *GetMetadata(const void *object); + void SetMetadata(const void *object, ClangASTMetadata &metadata); + bool HasMetadata(const void *object); + + static ClangExternalASTSourceCommon * + Lookup(clang::ExternalASTSource *source); +private: typedef llvm::DenseMap MetadataMap; MetadataMap m_metadata; - uint64_t m_magic; ///< Because we don't have RTTI, we must take it - ///< on faith that any valid ExternalASTSource that - ///< we try to use the *Metadata APIs on inherits - ///< from ClangExternalASTSourceCommon. This magic - ///< number exists to enforce that. }; } diff --git a/include/lldb/Symbol/CompactUnwindInfo.h b/include/lldb/Symbol/CompactUnwindInfo.h new file mode 100644 index 000000000000..239eb3ac77ad --- /dev/null +++ b/include/lldb/Symbol/CompactUnwindInfo.h @@ -0,0 +1,155 @@ +//===-- CompactUnwindInfo.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CompactUnwindInfo_h_ +#define liblldb_CompactUnwindInfo_h_ + +#include + +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/RangeMap.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +// Compact Unwind info is an unwind format used on Darwin. The unwind instructions +// for typical compiler-generated functions can be expressed in a 32-bit encoding. +// The format includes a two-level index so the unwind information for a function +// can be found by two binary searches in the section. It can represent both +// stack frames that use a frame-pointer register and frameless functions, on +// i386/x86_64 for instance. When a function is too complex to be represented in +// the compact unwind format, it calls out to eh_frame unwind instructions. + +// On Mac OS X / iOS, a function will have either a compact unwind representation +// or an eh_frame representation. If lldb is going to benefit from the compiler's +// description about saved register locations, it must be able to read both +// sources of information. + +class CompactUnwindInfo +{ +public: + + CompactUnwindInfo (ObjectFile& objfile, + lldb::SectionSP& section); + + ~CompactUnwindInfo(); + + bool + GetUnwindPlan (Target &target, Address addr, UnwindPlan& unwind_plan); + + bool + IsValid (const lldb::ProcessSP &process_sp); + +private: + + + // The top level index entries of the compact unwind info + // (internal representation of struct unwind_info_section_header_index_entry) + // There are relatively few of these (one per 500/1000 functions, depending on format) so + // creating them on first scan will not be too costly. + struct UnwindIndex + { + uint32_t function_offset; // The offset of the first function covered by this index + uint32_t second_level; // The offset (inside unwind_info sect) to the second level page for this index + // (either UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED) + uint32_t lsda_array_start;// The offset (inside unwind_info sect) LSDA array for this index + uint32_t lsda_array_end; // The offset to the LSDA array for the NEXT index + bool sentinal_entry; // There is an empty index at the end which provides the upper bound of + // function addresses that are described + + UnwindIndex() : + function_offset (0), + second_level (0), + lsda_array_start(0), + lsda_array_end(0), + sentinal_entry (false) + { } + + bool + operator< (const CompactUnwindInfo::UnwindIndex& rhs) const + { + return function_offset < rhs.function_offset; + } + + bool + operator== (const CompactUnwindInfo::UnwindIndex& rhs) const + { + return function_offset == rhs.function_offset; + } + + }; + + // An internal object used to store the information we retrieve about a function -- + // the encoding bits and possibly the LSDA/personality function. + struct FunctionInfo + { + uint32_t encoding; // compact encoding 32-bit value for this function + Address lsda_address; // the address of the LSDA data for this function + Address personality_ptr_address; // the address where the personality routine addr can be found + + uint32_t valid_range_offset_start; // first offset that this encoding is valid for (start of the function) + uint32_t valid_range_offset_end; // the offset of the start of the next function + FunctionInfo () : encoding(0), lsda_address(), personality_ptr_address(), valid_range_offset_start(0), valid_range_offset_end(0) { } + }; + + struct UnwindHeader + { + uint32_t version; + uint32_t common_encodings_array_offset; + uint32_t common_encodings_array_count; + uint32_t personality_array_offset; + uint32_t personality_array_count; + + UnwindHeader () : common_encodings_array_offset (0), common_encodings_array_count (0), personality_array_offset (0), personality_array_count (0) { } + }; + + void + ScanIndex(const lldb::ProcessSP &process_sp); + + bool + GetCompactUnwindInfoForFunction (Target &target, Address address, FunctionInfo &unwind_info); + + lldb::offset_t + BinarySearchRegularSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset, uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset); + + uint32_t + BinarySearchCompressedSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset_to_find, uint32_t function_offset_base, uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset); + + uint32_t + GetLSDAForFunctionOffset (uint32_t lsda_offset, uint32_t lsda_count, uint32_t function_offset); + + bool + CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start); + + bool + CreateUnwindPlan_i386 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start); + + ObjectFile &m_objfile; + lldb::SectionSP m_section_sp; + lldb::DataBufferSP m_section_contents_if_encrypted; // if the binary is encrypted, read the sect contents + // out of live memory and cache them here + Mutex m_mutex; + std::vector m_indexes; + + LazyBool m_indexes_computed; // eLazyBoolYes once we've tried to parse the unwind info + // eLazyBoolNo means we cannot parse the unwind info & should not retry + // eLazyBoolCalculate means we haven't tried to parse it yet + + DataExtractor m_unwindinfo_data; + bool m_unwindinfo_data_computed; // true once we've mapped in the unwindinfo data + + UnwindHeader m_unwind_header; +}; + +} // namespace lldb_private + +#endif // liblldb_CompactUnwindInfo_h_ diff --git a/include/lldb/Symbol/DWARFCallFrameInfo.h b/include/lldb/Symbol/DWARFCallFrameInfo.h index e67a5a2a8e2c..27d1a52b49f8 100644 --- a/include/lldb/Symbol/DWARFCallFrameInfo.h +++ b/include/lldb/Symbol/DWARFCallFrameInfo.h @@ -91,11 +91,17 @@ private: dw_offset_t inst_offset; // offset of CIE instructions in mCFIData uint32_t inst_length; // length of CIE instructions in mCFIData uint8_t ptr_encoding; + uint8_t lsda_addr_encoding; // The encoding of the LSDA address in the FDE augmentation data + lldb::addr_t personality_loc; // (file) address of the pointer to the personality routine lldb_private::UnwindPlan::Row initial_row; CIE(dw_offset_t offset) : cie_offset(offset), version (-1), code_align (0), data_align (0), return_addr_reg_num (LLDB_INVALID_REGNUM), inst_offset (0), - inst_length (0), ptr_encoding (0), initial_row() {} + inst_length (0), ptr_encoding (0), + lsda_addr_encoding (DW_EH_PE_omit), personality_loc (LLDB_INVALID_ADDRESS), + initial_row () + { + } }; typedef std::shared_ptr CIESP; diff --git a/include/lldb/Symbol/DeclVendor.h b/include/lldb/Symbol/DeclVendor.h new file mode 100644 index 000000000000..ffba71c9299f --- /dev/null +++ b/include/lldb/Symbol/DeclVendor.h @@ -0,0 +1,73 @@ +//===-- DeclVendor.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_DeclVendor_h_ +#define liblldb_DeclVendor_h_ + +#include "lldb/Core/ClangForward.h" + +#include + +namespace lldb_private { + +//---------------------------------------------------------------------- +// The Decl vendor class is intended as a generic interface to search +// for named declarations that are not necessarily backed by a specific +// symbol file. +//---------------------------------------------------------------------- +class DeclVendor +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + DeclVendor() + { + } + + virtual + ~DeclVendor() + { + } + + //------------------------------------------------------------------ + /// Look up the set of Decls that the DeclVendor currently knows about + /// matching a given name. + /// + /// @param[in] name + /// The name to look for. + /// + /// @param[in] append + /// If true, FindDecls will clear "decls" when it starts. + /// + /// @param[in] max_matches + /// The maximum number of Decls to return. UINT32_MAX means "as + /// many as possible." + /// + /// @return + /// The number of Decls added to decls; will not exceed + /// max_matches. + //------------------------------------------------------------------ + virtual uint32_t + FindDecls (const ConstString &name, + bool append, + uint32_t max_matches, + std::vector &decls) = 0; + +private: + //------------------------------------------------------------------ + // For DeclVendor only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (DeclVendor); +}; + + +} // namespace lldb_private + +#endif diff --git a/include/lldb/Symbol/FuncUnwinders.h b/include/lldb/Symbol/FuncUnwinders.h index 0cf584239f95..1e579c42acb8 100644 --- a/include/lldb/Symbol/FuncUnwinders.h +++ b/include/lldb/Symbol/FuncUnwinders.h @@ -1,6 +1,8 @@ #ifndef liblldb_FuncUnwinders_h #define liblldb_FuncUnwinders_h +#include + #include "lldb/Core/AddressRange.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/AddressRange.h" @@ -16,7 +18,8 @@ public: // FuncUnwinders objects are used to track UnwindPlans for a function // (named or not - really just an address range) - // We'll record three different UnwindPlans for each address range: + // We'll record four different UnwindPlans for each address range: + // // 1. Unwinding from a call site (a valid exception throw location) // This is often sourced from the eh_frame exception handling info // 2. Unwinding from a non-call site (any location in the function) @@ -41,7 +44,7 @@ public: // offset value will have already been decremented by 1 to stay within the bounds of the // correct function body. lldb::UnwindPlanSP - GetUnwindPlanAtCallSite (int current_offset); + GetUnwindPlanAtCallSite (Target &target, int current_offset); lldb::UnwindPlanSP GetUnwindPlanAtNonCallSite (Target& target, lldb_private::Thread& thread, int current_offset); @@ -67,13 +70,43 @@ public: return m_range.ContainsFileAddress (addr); } - // When we're doing an unwind using the UnwindPlanAtNonCallSite and we find an - // impossible unwind condition, we know that the UnwindPlan is invalid. Calling - // this method on the FuncUnwinder will tell it to replace that UnwindPlan with - // the architectural default UnwindPlan so hopefully our stack walk will get past - // this frame. - void - InvalidateNonCallSiteUnwindPlan (lldb_private::Thread& Thread); + // A function may have a Language Specific Data Area specified -- a block of data in + // the object file which is used in the processing of an exception throw / catch. + // If any of the UnwindPlans have the address of the LSDA region for this function, + // this will return it. + Address + GetLSDAAddress (Target &target); + + // A function may have a Personality Routine associated with it -- used in the + // processing of throwing an exception. If any of the UnwindPlans have the + // address of the personality routine, this will return it. Read the target-pointer + // at this address to get the personality function address. + Address + GetPersonalityRoutinePtrAddress (Target &target); + + + + // The following methods to retrieve specific unwind plans should rarely be used. + // Instead, clients should ask for the *behavior* they are looking for, using one + // of the above UnwindPlan retrieval methods. + + lldb::UnwindPlanSP + GetAssemblyUnwindPlan (Target &target, Thread &thread, int current_offset); + + lldb::UnwindPlanSP + GetEHFrameUnwindPlan (Target &target, int current_offset); + + lldb::UnwindPlanSP + GetEHFrameAugmentedUnwindPlan (Target &target, Thread &thread, int current_offset); + + lldb::UnwindPlanSP + GetCompactUnwindUnwindPlan (Target &target, int current_offset); + + lldb::UnwindPlanSP + GetArchDefaultUnwindPlan (Thread &thread); + + lldb::UnwindPlanSP + GetArchDefaultAtFuncEntryUnwindPlan (Thread &thread); private: @@ -84,19 +117,25 @@ private: AddressRange m_range; Mutex m_mutex; - lldb::UnwindPlanSP m_unwind_plan_call_site_sp; - lldb::UnwindPlanSP m_unwind_plan_non_call_site_sp; - lldb::UnwindPlanSP m_unwind_plan_fast_sp; - lldb::UnwindPlanSP m_unwind_plan_arch_default_sp; - lldb::UnwindPlanSP m_unwind_plan_arch_default_at_func_entry_sp; - - bool m_tried_unwind_at_call_site:1, - m_tried_unwind_at_non_call_site:1, + + lldb::UnwindPlanSP m_unwind_plan_assembly_sp; + lldb::UnwindPlanSP m_unwind_plan_eh_frame_sp; + lldb::UnwindPlanSP m_unwind_plan_eh_frame_augmented_sp; // augmented by assembly inspection so it's valid everywhere + std::vector m_unwind_plan_compact_unwind; + lldb::UnwindPlanSP m_unwind_plan_fast_sp; + lldb::UnwindPlanSP m_unwind_plan_arch_default_sp; + lldb::UnwindPlanSP m_unwind_plan_arch_default_at_func_entry_sp; + + // Fetching the UnwindPlans can be expensive - if we've already attempted + // to get one & failed, don't try again. + bool m_tried_unwind_plan_assembly:1, + m_tried_unwind_plan_eh_frame:1, + m_tried_unwind_plan_eh_frame_augmented:1, + m_tried_unwind_plan_compact_unwind:1, m_tried_unwind_fast:1, m_tried_unwind_arch_default:1, m_tried_unwind_arch_default_at_func_entry:1; - - + Address m_first_non_prologue_insn; DISALLOW_COPY_AND_ASSIGN (FuncUnwinders); diff --git a/include/lldb/Symbol/SymbolContext.h b/include/lldb/Symbol/SymbolContext.h index c26b7a0b9a10..d40d1453cb17 100644 --- a/include/lldb/Symbol/SymbolContext.h +++ b/include/lldb/Symbol/SymbolContext.h @@ -168,7 +168,8 @@ public: const Address &so_addr, bool show_fullpaths, bool show_module, - bool show_inlined_frames) const; + bool show_inlined_frames, + bool show_function_arguments) const; //------------------------------------------------------------------ /// Get the address range contained within a symbol context. diff --git a/include/lldb/Symbol/Type.h b/include/lldb/Symbol/Type.h index eaa150e78ace..51bd3dd82c92 100644 --- a/include/lldb/Symbol/Type.h +++ b/include/lldb/Symbol/Type.h @@ -810,6 +810,83 @@ private: TypePair m_type_pair; ConstString m_type_name; }; + +class TypeMemberFunctionImpl +{ +public: + TypeMemberFunctionImpl() : + m_type(), + m_objc_method_decl(nullptr), + m_name(), + m_kind(lldb::eMemberFunctionKindUnknown) + { + } + + TypeMemberFunctionImpl (const ClangASTType& type, + const std::string& name, + const lldb::MemberFunctionKind& kind) : + m_type(type), + m_objc_method_decl(nullptr), + m_name(name), + m_kind(kind) + { + } + + TypeMemberFunctionImpl (clang::ObjCMethodDecl *method, + const std::string& name, + const lldb::MemberFunctionKind& kind) : + m_type(), + m_objc_method_decl(method), + m_name(name), + m_kind(kind) + { + } + + TypeMemberFunctionImpl (const TypeMemberFunctionImpl& rhs) : + m_type(rhs.m_type), + m_objc_method_decl(rhs.m_objc_method_decl), + m_name(rhs.m_name), + m_kind(rhs.m_kind) + { + } + + TypeMemberFunctionImpl& + operator = (const TypeMemberFunctionImpl& rhs); + + bool + IsValid (); + + ConstString + GetName () const; + + ClangASTType + GetType () const; + + ClangASTType + GetReturnType () const; + + size_t + GetNumArguments () const; + + ClangASTType + GetArgumentAtIndex (size_t idx) const; + + lldb::MemberFunctionKind + GetKind () const; + + bool + GetDescription (Stream& stream); + +protected: + std::string + GetPrintableTypeName (); + +private: + ClangASTType m_type; + clang::ObjCMethodDecl *m_objc_method_decl; + ConstString m_name; + lldb::MemberFunctionKind m_kind; +}; class TypeEnumMemberImpl { diff --git a/include/lldb/Symbol/TypeVendor.h b/include/lldb/Symbol/TypeVendor.h deleted file mode 100644 index 559b21eeb95a..000000000000 --- a/include/lldb/Symbol/TypeVendor.h +++ /dev/null @@ -1,61 +0,0 @@ -//===-- TypeVendor.h --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_TypeVendor_h_ -#define liblldb_TypeVendor_h_ - -#include "lldb/Core/ClangForward.h" - -namespace lldb_private { - -//---------------------------------------------------------------------- -// The type vendor class is intended as a generic interface to search -// for Clang types that are not necessarily backed by a specific symbol -// file. -//---------------------------------------------------------------------- -class TypeVendor -{ -public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - TypeVendor() - { - } - - virtual - ~TypeVendor() - { - } - - virtual uint32_t - FindTypes (const ConstString &name, - bool append, - uint32_t max_matches, - std::vector &types) = 0; - - virtual clang::ASTContext * - GetClangASTContext () = 0; - -protected: - //------------------------------------------------------------------ - // Classes that inherit from TypeVendor can see and modify these - //------------------------------------------------------------------ - -private: - //------------------------------------------------------------------ - // For TypeVendor only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (TypeVendor); -}; - - -} // namespace lldb_private - -#endif diff --git a/include/lldb/Symbol/UnwindPlan.h b/include/lldb/Symbol/UnwindPlan.h index e1b146fe219e..c482739cb8f6 100644 --- a/include/lldb/Symbol/UnwindPlan.h +++ b/include/lldb/Symbol/UnwindPlan.h @@ -58,13 +58,13 @@ public: atDWARFExpression, // reg = deref(eval(dwarf_expr)) isDWARFExpression // reg = eval(dwarf_expr) }; - + RegisterLocation() : m_type(unspecified), m_location() { } - + bool operator == (const RegisterLocation& rhs) const; @@ -242,6 +242,7 @@ public: Row (const UnwindPlan::Row& rhs) : m_offset (rhs.m_offset), + m_cfa_type (rhs.m_cfa_type), m_cfa_reg_num (rhs.m_cfa_reg_num), m_cfa_offset (rhs.m_cfa_offset), m_register_locations (rhs.m_register_locations) @@ -256,7 +257,10 @@ public: void SetRegisterInfo (uint32_t reg_num, const RegisterLocation register_location); - + + void + RemoveRegisterInfo (uint32_t reg_num); + lldb::addr_t GetOffset() const { @@ -275,12 +279,49 @@ public: m_offset += offset; } + // How we can reconstruct the CFA address for this stack frame, at this location + enum CFAType + { + CFAIsRegisterPlusOffset, // the CFA value in a register plus (or minus) an offset + CFAIsRegisterDereferenced // the address in a register is dereferenced to get CFA value + }; + + CFAType + GetCFAType () const + { + return m_cfa_type; + } + + void + SetCFAType (CFAType cfa_type) + { + m_cfa_type = cfa_type; + } + + // If GetCFAType() is CFAIsRegisterPlusOffset, add GetCFAOffset to the reg value to get CFA value + // If GetCFAType() is CFAIsRegisterDereferenced, dereference the addr in the reg to get CFA value uint32_t GetCFARegister () const { return m_cfa_reg_num; } + void + SetCFARegister (uint32_t reg_num); + + // This should not be used when GetCFAType() is CFAIsRegisterDereferenced; will return 0 in that case. + int32_t + GetCFAOffset () const + { + return m_cfa_offset; + } + + void + SetCFAOffset (int32_t offset) + { + m_cfa_offset = offset; + } + bool SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, int32_t offset, @@ -309,23 +350,6 @@ public: SetRegisterLocationToSame (uint32_t reg_num, bool must_replace); - - - void - SetCFARegister (uint32_t reg_num); - - int32_t - GetCFAOffset () const - { - return m_cfa_offset; - } - - void - SetCFAOffset (int32_t offset) - { - m_cfa_offset = offset; - } - void Clear (); @@ -335,8 +359,15 @@ public: protected: typedef std::map collection; lldb::addr_t m_offset; // Offset into the function for this row + + CFAType m_cfa_type; + + // If m_cfa_type == CFAIsRegisterPlusOffset, the CFA address is computed as m_cfa_reg_num + m_cfa_offset + // If m_cfa_type == CFAIsRegisterDereferenced, the CFA address is computed as *(m_cfa_reg_num) - i.e. the + // address in m_cfa_reg_num is dereferenced and the pointer value read is the CFA addr. uint32_t m_cfa_reg_num; // The Call Frame Address register number int32_t m_cfa_offset; // The offset from the CFA for this row + collection m_register_locations; }; // class Row @@ -351,7 +382,9 @@ public: m_return_addr_register (LLDB_INVALID_REGNUM), m_source_name (), m_plan_is_sourced_from_compiler (eLazyBoolCalculate), - m_plan_is_valid_at_all_instruction_locations (eLazyBoolCalculate) + m_plan_is_valid_at_all_instruction_locations (eLazyBoolCalculate), + m_lsda_address (), + m_personality_func_addr () { } @@ -477,11 +510,39 @@ public: m_plan_valid_address_range.Clear(); m_register_kind = lldb::eRegisterKindDWARF; m_source_name.Clear(); + m_plan_is_sourced_from_compiler = eLazyBoolCalculate; + m_plan_is_valid_at_all_instruction_locations = eLazyBoolCalculate; + m_lsda_address.Clear(); + m_personality_func_addr.Clear(); } const RegisterInfo * GetRegisterInfo (Thread* thread, uint32_t reg_num) const; + Address + GetLSDAAddress () const + { + return m_lsda_address; + } + + void + SetLSDAAddress (Address lsda_addr) + { + m_lsda_address = lsda_addr; + } + + Address + GetPersonalityFunctionPtr () const + { + return m_personality_func_addr; + } + + void + SetPersonalityFunctionPtr (Address presonality_func_ptr) + { + m_personality_func_addr = presonality_func_ptr; + } + private: @@ -495,6 +556,11 @@ private: lldb_private::ConstString m_source_name; // for logging, where this UnwindPlan originated from lldb_private::LazyBool m_plan_is_sourced_from_compiler; lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations; + + Address m_lsda_address; // Where the language specific data area exists in the module - used + // in exception handling. + Address m_personality_func_addr; // The address of a pointer to the personality function - used in + // exception handling. }; // class UnwindPlan } // namespace lldb_private diff --git a/include/lldb/Symbol/UnwindTable.h b/include/lldb/Symbol/UnwindTable.h index 3a89f9f1f3c6..38d3ff6dd3c9 100644 --- a/include/lldb/Symbol/UnwindTable.h +++ b/include/lldb/Symbol/UnwindTable.h @@ -31,6 +31,9 @@ public: lldb_private::DWARFCallFrameInfo * GetEHFrameInfo (); + lldb_private::CompactUnwindInfo * + GetCompactUnwindInfo (); + lldb::FuncUnwindersSP GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc); @@ -63,6 +66,7 @@ private: Mutex m_mutex; DWARFCallFrameInfo* m_eh_frame; + CompactUnwindInfo *m_compact_unwind; DISALLOW_COPY_AND_ASSIGN (UnwindTable); }; diff --git a/include/lldb/Target/ABI.h b/include/lldb/Target/ABI.h index 8809c0047fa0..cfd214d28874 100644 --- a/include/lldb/Target/ABI.h +++ b/include/lldb/Target/ABI.h @@ -112,12 +112,6 @@ public: virtual bool RegisterIsVolatile (const RegisterInfo *reg_info) = 0; - // Should return true if your ABI uses frames when doing stack backtraces. This - // means a frame pointer is used that points to the previous stack frame in some - // way or another. - virtual bool - StackUsesFrames () = 0; - // Should take a look at a call frame address (CFA) which is just the stack // pointer value upon entry to a function. ABIs usually impose alignment // restrictions (4, 8 or 16 byte aligned), and zero is usually not allowed. @@ -143,15 +137,6 @@ public: virtual const RegisterInfo * GetRegisterInfoArray (uint32_t &count) = 0; - // Some architectures (e.g. x86) will push the return address on the stack and decrement - // the stack pointer when making a function call. This means that every stack frame will - // have a unique CFA. - // Other architectures (e.g. arm) pass the return address in a register so it is possible - // to have a frame on a backtrace that does not push anything on the stack or change the - // CFA. - virtual bool - FunctionCallsChangeCFA () = 0; - bool GetRegisterInfoByName (const ConstString &name, RegisterInfo &info); diff --git a/include/lldb/Target/CPPLanguageRuntime.h b/include/lldb/Target/CPPLanguageRuntime.h index daf8a67d2a9d..43df9e67add0 100644 --- a/include/lldb/Target/CPPLanguageRuntime.h +++ b/include/lldb/Target/CPPLanguageRuntime.h @@ -65,8 +65,10 @@ public: Clear(); bool - IsValid () const + IsValid () { + if (!m_parsed) + Parse(); if (m_parse_error) return false; if (m_type == eTypeInvalid) @@ -132,9 +134,16 @@ public: static bool IsCPPMangledName(const char *name); - + + // Extract C++ context and identifier from a string using heuristic matching (as opposed to + // CPPLanguageRuntime::MethodName which has to have a fully qualified C++ name with parens and arguments. + // If the name is a lone C identifier (e.g. C) or a qualified C identifier (e.g. A::B::C) it will return true, + // and identifier will be the identifier (C and C respectively) and the context will be "" and "A::B::" respectively. + // If the name fails the heuristic matching for a qualified or unqualified C/C++ identifier, then it will return false + // and identifier and context will be unchanged. + static bool - StripNamespacesFromVariableName (const char *name, const char *&base_name_start, const char *&base_name_end); + ExtractContextAndIdentifier (const char *name, llvm::StringRef &context, llvm::StringRef &identifier); // in some cases, compilers will output different names for one same type. when that happens, it might be impossible // to construct SBType objects for a valid type, because the name that is available is not the same as the name that diff --git a/include/lldb/Target/FileAction.h b/include/lldb/Target/FileAction.h index db84c0ef468c..228a9e6098c1 100644 --- a/include/lldb/Target/FileAction.h +++ b/include/lldb/Target/FileAction.h @@ -56,6 +56,9 @@ class FileAction const char *GetPath() const; + void + Dump (Stream &stream) const; + protected: Action m_action; // The action for this file int m_fd; // An existing file descriptor diff --git a/include/lldb/Target/InstrumentationRuntime.h b/include/lldb/Target/InstrumentationRuntime.h new file mode 100644 index 000000000000..70aa62908406 --- /dev/null +++ b/include/lldb/Target/InstrumentationRuntime.h @@ -0,0 +1,47 @@ +//===-- InstrumentationRuntime.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_InstrumentationRuntime_h_ +#define liblldb_InstrumentationRuntime_h_ + +// C Includes +// C++ Includes +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/lldb-types.h" +#include "lldb/Core/PluginInterface.h" + +namespace lldb_private { + +typedef std::map InstrumentationRuntimeCollection; + +class InstrumentationRuntime : + public std::enable_shared_from_this, + public PluginInterface +{ +public: + + static void + ModulesDidLoad(lldb_private::ModuleList &module_list, Process *process, InstrumentationRuntimeCollection &runtimes); + + virtual void + ModulesDidLoad(lldb_private::ModuleList &module_list); + + virtual bool + IsActive(); + +}; + +} // namespace lldb_private + +#endif // liblldb_InstrumentationRuntime_h_ diff --git a/include/lldb/Target/InstrumentationRuntimeStopInfo.h b/include/lldb/Target/InstrumentationRuntimeStopInfo.h new file mode 100644 index 000000000000..624267ce8221 --- /dev/null +++ b/include/lldb/Target/InstrumentationRuntimeStopInfo.h @@ -0,0 +1,52 @@ +//===-- InstrumentationRuntimeStopInfo.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_InstrumentationRuntimeStopInfo_h_ +#define liblldb_InstrumentationRuntimeStopInfo_h_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/Target/StopInfo.h" +#include "lldb/Core/StructuredData.h" + +namespace lldb_private { + +class InstrumentationRuntimeStopInfo : public StopInfo +{ +public: + + virtual ~InstrumentationRuntimeStopInfo() + { + } + + virtual lldb::StopReason + GetStopReason () const + { + return lldb::eStopReasonInstrumentation; + } + + virtual const char * + GetDescription (); + + static lldb::StopInfoSP + CreateStopReasonWithInstrumentationData (Thread &thread, std::string description, StructuredData::ObjectSP additional_data); + +private: + + InstrumentationRuntimeStopInfo(Thread &thread, std::string description, StructuredData::ObjectSP additional_data); + +}; + +} // namespace lldb_private + +#endif // liblldb_InstrumentationRuntimeStopInfo_h_ diff --git a/include/lldb/Target/MemoryHistory.h b/include/lldb/Target/MemoryHistory.h new file mode 100644 index 000000000000..b3bd62d6547c --- /dev/null +++ b/include/lldb/Target/MemoryHistory.h @@ -0,0 +1,42 @@ +//===-- MemoryHistory.h ---------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_MemoryHistory_h_ +#define liblldb_MemoryHistory_h_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/lldb-types.h" +#include "lldb/Core/PluginInterface.h" + +namespace lldb_private { + +typedef std::vector HistoryThreads; + +class MemoryHistory : + public std::enable_shared_from_this, + public PluginInterface +{ +public: + + static lldb::MemoryHistorySP + FindPlugin (const lldb::ProcessSP process); + + virtual HistoryThreads + GetHistoryThreads(lldb::addr_t address) = 0; +}; + +} // namespace lldb_private + +#endif // liblldb_MemoryHistory_h_ diff --git a/include/lldb/Target/ObjCLanguageRuntime.h b/include/lldb/Target/ObjCLanguageRuntime.h index 12254f942e42..a3fee91428fa 100644 --- a/include/lldb/Target/ObjCLanguageRuntime.h +++ b/include/lldb/Target/ObjCLanguageRuntime.h @@ -21,8 +21,8 @@ #include "lldb/lldb-private.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/DeclVendor.h" #include "lldb/Symbol/Type.h" -#include "lldb/Symbol/TypeVendor.h" #include "lldb/Target/LanguageRuntime.h" namespace lldb_private { @@ -166,6 +166,9 @@ public: virtual ClassDescriptorSP GetSuperclass () = 0; + virtual ClassDescriptorSP + GetMetaclass () const = 0; + // virtual if any implementation has some other version-specific rules // but for the known v1/v2 this is all that needs to be done virtual bool @@ -275,10 +278,10 @@ public: class EncodingToType { public: - virtual ClangASTType RealizeType (ClangASTContext& ast_ctx, const char* name, bool allow_unknownanytype); - virtual ClangASTType RealizeType (const char* name, bool allow_unknownanytype); + virtual ClangASTType RealizeType (ClangASTContext& ast_ctx, const char* name, bool for_expression); + virtual ClangASTType RealizeType (const char* name, bool for_expression); - virtual ClangASTType RealizeType (clang::ASTContext& ast_ctx, const char* name, bool allow_unknownanytype) = 0; + virtual ClangASTType RealizeType (clang::ASTContext& ast_ctx, const char* name, bool for_expression) = 0; virtual ~EncodingToType(); @@ -382,8 +385,8 @@ public: virtual ObjCISA GetParentClass(ObjCISA isa); - virtual TypeVendor * - GetTypeVendor() + virtual DeclVendor * + GetDeclVendor() { return NULL; } diff --git a/include/lldb/Target/Platform.h b/include/lldb/Target/Platform.h index e3d6abe3f398..8b14cc2a0ece 100644 --- a/include/lldb/Target/Platform.h +++ b/include/lldb/Target/Platform.h @@ -62,7 +62,7 @@ namespace lldb_private { /// or attaching to processes unless another platform is specified. //------------------------------------------------------------------ static lldb::PlatformSP - GetDefaultPlatform (); + GetHostPlatform (); static lldb::PlatformSP GetPlatformForArchitecture (const ArchSpec &arch, @@ -72,10 +72,14 @@ namespace lldb_private { GetHostPlatformName (); static void - SetDefaultPlatform (const lldb::PlatformSP &platform_sp); + SetHostPlatform (const lldb::PlatformSP &platform_sp); + // Find an existing platform plug-in by name static lldb::PlatformSP - Create (const char *platform_name, Error &error); + Find (const ConstString &name); + + static lldb::PlatformSP + Create (const ConstString &name, Error &error); static lldb::PlatformSP Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &error); @@ -114,8 +118,8 @@ namespace lldb_private { /// An optional name of a specific platform plug-in that /// should be used. If NULL, pick the best plug-in. //------------------------------------------------------------------ - static Platform* - FindPlugin (Process *process, const ConstString &plugin_name); +// static lldb::PlatformSP +// FindPlugin (Process *process, const ConstString &plugin_name); //------------------------------------------------------------------ /// Set the target's executable based off of the existing @@ -137,8 +141,7 @@ namespace lldb_private { /// a suitable executable, \b false otherwise. //------------------------------------------------------------------ virtual Error - ResolveExecutable (const FileSpec &exe_file, - const ArchSpec &arch, + ResolveExecutable (const ModuleSpec &module_spec, lldb::ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr); @@ -409,7 +412,6 @@ namespace lldb_private { DebugProcess (ProcessLaunchInfo &launch_info, Debugger &debugger, Target *target, // Can be NULL, if NULL create a new target, else use existing one - Listener &listener, Error &error); //------------------------------------------------------------------ @@ -434,7 +436,6 @@ namespace lldb_private { Attach (ProcessAttachInfo &attach_info, Debugger &debugger, Target *target, // Can be NULL, if NULL create a new target, else use existing one - Listener &listener, Error &error) = 0; //------------------------------------------------------------------ @@ -559,7 +560,16 @@ namespace lldb_private { SetSDKBuild (const ConstString &sdk_build) { m_sdk_build = sdk_build; - } + } + + // Override this to return true if your platform supports Clang modules. + // You may also need to override AddClangModuleCompilationOptions to pass the right Clang flags for your platform. + virtual bool + SupportsModules () { return false; } + + // Appends the platform-specific options required to find the modules for the current platform. + virtual void + AddClangModuleCompilationOptions (std::vector &options); ConstString GetWorkingDirectory (); @@ -571,7 +581,7 @@ namespace lldb_private { // The platform will return "true" from this call if the passed in module happens to be one of these. virtual bool - ModuleIsExcludedForNonModuleSpecificSearches (Target &target, const lldb::ModuleSP &module_sp) + ModuleIsExcludedForUnconstrainedSearches (Target &target, const lldb::ModuleSP &module_sp) { return false; } diff --git a/include/lldb/Target/Process.h b/include/lldb/Target/Process.h index 641707c58deb..e04de511c797 100644 --- a/include/lldb/Target/Process.h +++ b/include/lldb/Target/Process.h @@ -38,6 +38,7 @@ #include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" +#include "lldb/Host/HostThread.h" #include "lldb/Host/ProcessRunLock.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/Options.h" @@ -51,6 +52,7 @@ #include "lldb/Target/ThreadList.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/PseudoTerminal.h" +#include "lldb/Target/InstrumentationRuntime.h" namespace lldb_private { @@ -60,7 +62,8 @@ namespace lldb_private { class ProcessProperties : public Properties { public: - ProcessProperties(bool is_global); + // Pass NULL for "process" if the ProcessProperties are to be the global copy + ProcessProperties (lldb_private::Process *process); virtual ~ProcessProperties(); @@ -68,6 +71,9 @@ public: bool GetDisableMemoryCache() const; + uint64_t + GetMemoryCacheLineSize () const; + Args GetExtraStartupCommands () const; @@ -103,6 +109,13 @@ public: void SetDetachKeepsStopped (bool keep_stopped); + +protected: + + static void + OptionValueChangedCallback (void *baton, OptionValue *option_value); + + Process * m_process; // Can be NULL for global ProcessProperties }; typedef std::shared_ptr ProcessPropertiesSP; @@ -223,6 +236,8 @@ class ProcessAttachInfo : public ProcessInstanceInfo public: ProcessAttachInfo() : ProcessInstanceInfo(), + m_listener_sp(), + m_hijack_listener_sp(), m_plugin_name (), m_resume_count (0), m_wait_for_launch (false), @@ -234,6 +249,8 @@ public: ProcessAttachInfo (const ProcessLaunchInfo &launch_info) : ProcessInstanceInfo(), + m_listener_sp(), + m_hijack_listener_sp(), m_plugin_name (), m_resume_count (0), m_wait_for_launch (false), @@ -244,6 +261,7 @@ public: ProcessInfo::operator= (launch_info); SetProcessPluginName (launch_info.GetProcessPluginName()); SetResumeCount (launch_info.GetResumeCount()); + SetListener(launch_info.GetListener()); SetHijackListener(launch_info.GetHijackListener()); m_detach_on_error = launch_info.GetDetachOnError(); } @@ -359,8 +377,26 @@ public: { m_detach_on_error = enable; } - + + // Get and set the actual listener that will be used for the process events + lldb::ListenerSP + GetListener () const + { + return m_listener_sp; + } + + void + SetListener (const lldb::ListenerSP &listener_sp) + { + m_listener_sp = listener_sp; + } + + + Listener & + GetListenerForProcess (Debugger &debugger); + protected: + lldb::ListenerSP m_listener_sp; lldb::ListenerSP m_hijack_listener_sp; std::string m_plugin_name; uint32_t m_resume_count; // How many times do we resume after launching @@ -1268,7 +1304,9 @@ public: //------------------------------------------------------------------ Error Resume(); - + + Error + ResumeSynchronous (Stream *stream); //------------------------------------------------------------------ /// Halts a running process. /// @@ -2447,17 +2485,26 @@ public: //------------------------------------------------------------------ /// Get any available STDOUT. /// - /// If the process was launched without supplying valid file paths - /// for stdin, stdout, and stderr, then the Process class might - /// try to cache the STDOUT for the process if it is able. Events - /// will be queued indicating that there is STDOUT available that - /// can be retrieved using this function. + /// Calling this method is a valid operation only if all of the + /// following conditions are true: + /// 1) The process was launched, and not attached to. + /// 2) The process was not launched with eLaunchFlagDisableSTDIO. + /// 3) The process was launched without supplying a valid file path + /// for STDOUT. + /// + /// Note that the implementation will probably need to start a read + /// thread in the background to make sure that the pipe is drained + /// and the STDOUT buffered appropriately, to prevent the process + /// from deadlocking trying to write to a full buffer. + /// + /// Events will be queued indicating that there is STDOUT available + /// that can be retrieved using this function. /// /// @param[out] buf /// A buffer that will receive any STDOUT bytes that are /// currently available. /// - /// @param[out] buf_size + /// @param[in] buf_size /// The size in bytes for the buffer \a buf. /// /// @return @@ -2471,13 +2518,22 @@ public: //------------------------------------------------------------------ /// Get any available STDERR. /// - /// If the process was launched without supplying valid file paths - /// for stdin, stdout, and stderr, then the Process class might - /// try to cache the STDERR for the process if it is able. Events - /// will be queued indicating that there is STDERR available that - /// can be retrieved using this function. + /// Calling this method is a valid operation only if all of the + /// following conditions are true: + /// 1) The process was launched, and not attached to. + /// 2) The process was not launched with eLaunchFlagDisableSTDIO. + /// 3) The process was launched without supplying a valid file path + /// for STDERR. /// - /// @param[out] buf + /// Note that the implementation will probably need to start a read + /// thread in the background to make sure that the pipe is drained + /// and the STDERR buffered appropriately, to prevent the process + /// from deadlocking trying to write to a full buffer. + /// + /// Events will be queued indicating that there is STDERR available + /// that can be retrieved using this function. + /// + /// @param[in] buf /// A buffer that will receive any STDERR bytes that are /// currently available. /// @@ -2492,6 +2548,27 @@ public: virtual size_t GetSTDERR (char *buf, size_t buf_size, Error &error); + //------------------------------------------------------------------ + /// Puts data into this process's STDIN. + /// + /// Calling this method is a valid operation only if all of the + /// following conditions are true: + /// 1) The process was launched, and not attached to. + /// 2) The process was not launched with eLaunchFlagDisableSTDIO. + /// 3) The process was launched without supplying a valid file path + /// for STDIN. + /// + /// @param[in] buf + /// A buffer that contains the data to write to the process's STDIN. + /// + /// @param[in] buf_size + /// The size in bytes for the buffer \a buf. + /// + /// @return + /// The number of bytes written into \a buf. If this value is + /// less than \a buf_size, another call to this function should + /// be made to write the rest of the data. + //------------------------------------------------------------------ virtual size_t PutSTDIN (const char *buf, size_t buf_size, Error &error) { @@ -2675,7 +2752,8 @@ public: WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr = NULL, bool wait_always = true, - Listener *hijack_listener = NULL); + Listener *hijack_listener = NULL, + Stream *stream = NULL); //-------------------------------------------------------------------------------------- @@ -2700,7 +2778,28 @@ public: WaitForStateChangedEvents (const TimeValue *timeout, lldb::EventSP &event_sp, Listener *hijack_listener); // Pass NULL to use builtin listener - + + //-------------------------------------------------------------------------------------- + /// Centralize the code that handles and prints descriptions for process state changes. + /// + /// @param[in] event_sp + /// The process state changed event + /// + /// @param[in] stream + /// The output stream to get the state change description + /// + /// @param[inout] pop_process_io_handler + /// If this value comes in set to \b true, then pop the Process IOHandler if needed. + /// Else this variable will be set to \b true or \b false to indicate if the process + /// needs to have its process IOHandler popped. + /// + /// @return + /// \b true if the event describes a process state changed event, \b false otherwise. + //-------------------------------------------------------------------------------------- + static bool + HandleProcessStateChangedEvent (const lldb::EventSP &event_sp, + Stream *stream, + bool &pop_process_io_handler); Event * PeekAtStateChangedEvents (); @@ -2723,6 +2822,7 @@ public: Process &m_process; }; friend class ProcessEventHijacker; + friend class ProcessProperties; //------------------------------------------------------------------ /// If you need to ensure that you and only you will hear about some public /// event, then make a new listener, set to listen to process events, and @@ -2776,7 +2876,12 @@ public: { return m_os_ap.get(); } - + + ArchSpec::StopInfoOverrideCallbackType + GetStopInfoOverrideCallback () const + { + return m_stop_info_override_callback; + } virtual LanguageRuntime * GetLanguageRuntime (lldb::LanguageType language, bool retry_if_null = true); @@ -2906,7 +3011,7 @@ public: ProcessRunLock & GetRunLock () { - if (Host::GetCurrentThread() == m_private_state_thread) + if (m_private_state_thread.EqualsThread(Host::GetCurrentThread())) return m_private_run_lock; else return m_public_run_lock; @@ -2919,6 +3024,12 @@ public: Error return_error ("Sending an event is not supported for this process."); return return_error; } + + lldb::ThreadCollectionSP + GetHistoryThreads(lldb::addr_t addr); + + lldb::InstrumentationRuntimeSP + GetInstrumentationRuntime(lldb::InstrumentationRuntimeType type); protected: @@ -3001,7 +3112,7 @@ protected: bool PrivateStateThreadIsValid () const { - return IS_VALID_LLDB_HOST_THREAD(m_private_state_thread); + return m_private_state_thread.IsJoinable(); } void @@ -3036,13 +3147,14 @@ protected: Broadcaster m_private_state_control_broadcaster; // This is the control broadcaster, used to pause, resume & stop the private state thread. Listener m_private_state_listener; // This is the listener for the private state thread. Predicate m_private_state_control_wait; /// This Predicate is used to signal that a control operation is complete. - lldb::thread_t m_private_state_thread; // Thread ID for the thread that watches internal state events + HostThread m_private_state_thread; // Thread ID for the thread that watches internal state events ProcessModID m_mod_id; ///< Tracks the state of the process over stops and other alterations. uint32_t m_process_unique_id; ///< Each lldb_private::Process class that is created gets a unique integer ID that increments with each new instance uint32_t m_thread_index_id; ///< Each thread is created with a 1 based index that won't get re-used. std::map m_thread_id_to_index_id_map; int m_exit_status; ///< The exit status of the process, or -1 if not set. std::string m_exit_string; ///< A textual description of why a process exited. + Mutex m_exit_status_mutex; ///< Mutex so m_exit_status m_exit_string can be safely accessed from multiple threads Mutex m_thread_mutex; ThreadList m_thread_list_real; ///< The threads for this process as are known to the protocol we are debugging with ThreadList m_thread_list; ///< The threads for this process as the user will see them. This is usually the same as @@ -3074,11 +3186,13 @@ protected: AllocatedMemoryCache m_allocated_memory_cache; bool m_should_detach; /// Should we detach if the process object goes away with an explicit call to Kill or Detach? LanguageRuntimeCollection m_language_runtimes; + InstrumentationRuntimeCollection m_instrumentation_runtimes; std::unique_ptr m_next_event_action_ap; std::vector m_pre_resume_actions; ProcessRunLock m_public_run_lock; ProcessRunLock m_private_run_lock; Predicate m_currently_handling_event; // This predicate is set in HandlePrivateEvent while all its business is being done. + ArchSpec::StopInfoOverrideCallbackType m_stop_info_override_callback; bool m_currently_handling_do_on_removals; bool m_resume_requested; // If m_currently_handling_event or m_currently_handling_do_on_removals are true, Resume will only request a resume, using this flag to check. bool m_finalize_called; @@ -3170,7 +3284,12 @@ protected: Error HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp); - + + bool + StateChangedIsExternallyHijacked(); + + void + LoadOperatingSystemPlugin(bool flush); private: //------------------------------------------------------------------ // For Process only diff --git a/include/lldb/Target/ProcessLaunchInfo.h b/include/lldb/Target/ProcessLaunchInfo.h index 77d829a7e476..897704488e5f 100644 --- a/include/lldb/Target/ProcessLaunchInfo.h +++ b/include/lldb/Target/ProcessLaunchInfo.h @@ -15,6 +15,7 @@ // LLDB Headers #include "lldb/Core/Flags.h" +#include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/ProcessInfo.h" @@ -105,11 +106,11 @@ namespace lldb_private void SetProcessPluginName (const char *plugin); - const char * + const FileSpec & GetShell () const; void - SetShell (const char * path); + SetShell (const FileSpec &shell); uint32_t GetResumeCount () const @@ -124,7 +125,7 @@ namespace lldb_private } bool - GetLaunchInSeparateProcessGroup () + GetLaunchInSeparateProcessGroup() const { return m_flags.Test(lldb::eLaunchFlagLaunchInSeparateProcessGroup); } @@ -148,17 +149,23 @@ namespace lldb_private bool monitor_signals); Host::MonitorChildProcessCallback - GetMonitorProcessCallback () + GetMonitorProcessCallback() const { return m_monitor_callback; } - const void* - GetMonitorProcessBaton () const + void * + GetMonitorProcessBaton() const { return m_monitor_callback_baton; } + bool + GetMonitorSignals() const + { + return m_monitor_signals; + } + // If the LaunchInfo has a monitor callback, then arrange to monitor the process. // Return true if the LaunchInfo has taken care of monitoring the process, and false if the // caller might want to monitor the process themselves. @@ -169,9 +176,25 @@ namespace lldb_private lldb_utility::PseudoTerminal & GetPTY () { - return m_pty; + return *m_pty; } + // Get and set the actual listener that will be used for the process events + lldb::ListenerSP + GetListener () const + { + return m_listener_sp; + } + + void + SetListener (const lldb::ListenerSP &listener_sp) + { + m_listener_sp = listener_sp; + } + + Listener & + GetListenerForProcess (Debugger &debugger); + lldb::ListenerSP GetHijackListener () const { @@ -184,7 +207,6 @@ namespace lldb_private m_hijack_listener_sp = listener_sp; } - void SetLaunchEventData (const char *data) { @@ -209,15 +231,16 @@ namespace lldb_private protected: std::string m_working_dir; std::string m_plugin_name; - std::string m_shell; + FileSpec m_shell; Flags m_flags; // Bitwise OR of bits from lldb::LaunchFlags std::vector m_file_actions; // File actions for any other files - lldb_utility::PseudoTerminal m_pty; + std::shared_ptr m_pty; uint32_t m_resume_count; // How many times do we resume after launching Host::MonitorChildProcessCallback m_monitor_callback; void *m_monitor_callback_baton; bool m_monitor_signals; std::string m_event_data; // A string passed to the plugin launch, having no meaning to the upper levels of lldb. + lldb::ListenerSP m_listener_sp; lldb::ListenerSP m_hijack_listener_sp; }; } diff --git a/include/lldb/Target/StackFrame.h b/include/lldb/Target/StackFrame.h index 1274dcc64bd3..95e21445be04 100644 --- a/include/lldb/Target/StackFrame.h +++ b/include/lldb/Target/StackFrame.h @@ -519,6 +519,7 @@ private: lldb::VariableListSP m_variable_list_sp; ValueObjectList m_variable_list_value_objects; // Value objects for each variable in m_variable_list_sp StreamString m_disassembly; + Mutex m_mutex; DISALLOW_COPY_AND_ASSIGN (StackFrame); }; diff --git a/include/lldb/Target/StopInfo.h b/include/lldb/Target/StopInfo.h index 8de40e852f4c..e0d029bcc956 100644 --- a/include/lldb/Target/StopInfo.h +++ b/include/lldb/Target/StopInfo.h @@ -18,6 +18,7 @@ // Project includes #include "lldb/lldb-public.h" #include "lldb/Target/Process.h" +#include "lldb/Core/StructuredData.h" namespace lldb_private { @@ -140,6 +141,12 @@ public: return m_override_should_stop == eLazyBoolYes; } + StructuredData::ObjectSP + GetExtendedInfo () + { + return m_extended_info; + } + static lldb::StopInfoSP CreateStopReasonWithBreakpointSiteID (Thread &thread, lldb::break_id_t break_id); @@ -211,6 +218,8 @@ protected: LazyBool m_override_should_notify; LazyBool m_override_should_stop; + StructuredData::ObjectSP m_extended_info; // The extended info for this stop info + // This determines whether the target has run since this stop info. // N.B. running to evaluate a user expression does not count. bool HasTargetRunSinceMe (); diff --git a/include/lldb/Target/Target.h b/include/lldb/Target/Target.h index 64f3edf0fc4f..a33734fd5b63 100644 --- a/include/lldb/Target/Target.h +++ b/include/lldb/Target/Target.h @@ -26,6 +26,7 @@ #include "lldb/Core/Event.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/UserSettingsController.h" +#include "lldb/Expression/ClangModulesDeclVendor.h" #include "lldb/Expression/ClangPersistentVariables.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/OptionValueBoolean.h" @@ -554,12 +555,20 @@ private: //------------------------------------------------------------------ Target (Debugger &debugger, const ArchSpec &target_arch, - const lldb::PlatformSP &platform_sp); + const lldb::PlatformSP &platform_sp, + bool is_dummy_target); // Helper function. bool ProcessIsValid (); + // Copy breakpoints, stop hooks and so forth from the dummy target: + void + PrimeFromDummyTarget(Target *dummy_target); + + void + AddBreakpoint(lldb::BreakpointSP breakpoint_sp, bool internal); + public: ~Target(); @@ -607,8 +616,8 @@ public: Destroy(); Error - Launch (Listener &listener, - ProcessLaunchInfo &launch_info); + Launch (ProcessLaunchInfo &launch_info, + Stream *stream); // Optional stream to receive first stop info //------------------------------------------------------------------ // This part handles the breakpoints. @@ -954,9 +963,9 @@ public: //------------------------------------------------------------------ /// Return whether this FileSpec corresponds to a module that should be considered for general searches. /// - /// This API will be consulted by the SearchFilterForNonModuleSpecificSearches + /// This API will be consulted by the SearchFilterForUnconstrainedSearches /// and any module that returns \b true will not be searched. Note the - /// SearchFilterForNonModuleSpecificSearches is the search filter that + /// SearchFilterForUnconstrainedSearches is the search filter that /// gets used in the CreateBreakpoint calls when no modules is provided. /// /// The target call at present just consults the Platform's call of the @@ -968,14 +977,14 @@ public: /// @return \b true if the module should be excluded, \b false otherwise. //------------------------------------------------------------------ bool - ModuleIsExcludedForNonModuleSpecificSearches (const FileSpec &module_spec); + ModuleIsExcludedForUnconstrainedSearches (const FileSpec &module_spec); //------------------------------------------------------------------ /// Return whether this module should be considered for general searches. /// - /// This API will be consulted by the SearchFilterForNonModuleSpecificSearches + /// This API will be consulted by the SearchFilterForUnconstrainedSearches /// and any module that returns \b true will not be searched. Note the - /// SearchFilterForNonModuleSpecificSearches is the search filter that + /// SearchFilterForUnconstrainedSearches is the search filter that /// gets used in the CreateBreakpoint calls when no modules is provided. /// /// The target call at present just consults the Platform's call of the @@ -990,7 +999,7 @@ public: /// @return \b true if the module should be excluded, \b false otherwise. //------------------------------------------------------------------ bool - ModuleIsExcludedForNonModuleSpecificSearches (const lldb::ModuleSP &module_sp); + ModuleIsExcludedForUnconstrainedSearches (const lldb::ModuleSP &module_sp); ArchSpec & GetArchitecture () @@ -1132,6 +1141,9 @@ public: Error Install(ProcessLaunchInfo *launch_info); + bool + ResolveFileAddress (lldb::addr_t load_addr, + Address &so_addr); bool ResolveLoadAddress (lldb::addr_t load_addr, @@ -1143,6 +1155,12 @@ public: lldb::addr_t load_addr, bool warn_multiple = false); + size_t + UnloadModuleSections (const lldb::ModuleSP &module_sp); + + size_t + UnloadModuleSections (const ModuleList &module_list); + bool SetSectionUnloaded (const lldb::SectionSP §ion_sp); @@ -1332,6 +1350,9 @@ public: SourceManager & GetSourceManager (); + + ClangModulesDeclVendor * + GetClangModulesDeclVendor (); //------------------------------------------------------------------ // Methods. @@ -1369,6 +1390,7 @@ protected: std::unique_ptr m_scratch_ast_context_ap; std::unique_ptr m_scratch_ast_source_ap; std::unique_ptr m_ast_importer_ap; + std::unique_ptr m_clang_modules_decl_vendor_ap; ClangPersistentVariables m_persistent_variables; ///< These are the persistent variables associated with this process for the expression parser. std::unique_ptr m_source_manager_ap; @@ -1378,6 +1400,7 @@ protected: lldb::user_id_t m_stop_hook_next_id; bool m_valid; bool m_suppress_stop_hooks; + bool m_is_dummy_target; static void ImageSearchPathsChanged (const PathMappingList &path_list, diff --git a/include/lldb/Target/TargetList.h b/include/lldb/Target/TargetList.h index 6abf13e8704c..27e46ba81a70 100644 --- a/include/lldb/Target/TargetList.h +++ b/include/lldb/Target/TargetList.h @@ -221,16 +221,42 @@ public: lldb::TargetSP GetSelectedTarget (); - protected: typedef std::vector collection; //------------------------------------------------------------------ // Member variables. //------------------------------------------------------------------ collection m_target_list; + lldb::TargetSP m_dummy_target_sp; mutable Mutex m_target_list_mutex; uint32_t m_selected_target_idx; private: + lldb::TargetSP + GetDummyTarget (lldb_private::Debugger &debugger); + + Error + CreateDummyTarget (Debugger &debugger, + const char *specified_arch_name, + lldb::TargetSP &target_sp); + + Error + CreateTargetInternal (Debugger &debugger, + const char *user_exe_path, + const char *triple_cstr, + bool get_dependent_files, + const OptionGroupPlatform *platform_options, + lldb::TargetSP &target_sp, + bool is_dummy_target); + + Error + CreateTargetInternal (Debugger &debugger, + const char *user_exe_path, + const ArchSpec& arch, + bool get_dependent_modules, + lldb::PlatformSP &platform_sp, + lldb::TargetSP &target_sp, + bool is_dummy_target); + DISALLOW_COPY_AND_ASSIGN (TargetList); }; diff --git a/include/lldb/Target/Thread.h b/include/lldb/Target/Thread.h index cba09e164105..25c0c0e92bec 100644 --- a/include/lldb/Target/Thread.h +++ b/include/lldb/Target/Thread.h @@ -535,7 +535,7 @@ public: DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx); bool - GetDescription (Stream &s, lldb::DescriptionLevel level, bool json_output); + GetDescription (Stream &s, lldb::DescriptionLevel level, bool print_json_thread, bool print_json_stopinfo); //------------------------------------------------------------------ /// Default implementation for stepping into. @@ -912,6 +912,11 @@ public: bool stop_others, uint32_t frame_idx); + virtual lldb::ThreadPlanSP + QueueThreadPlanForStepScripted (bool abort_other_plans, + const char *class_name, + bool stop_other_threads); + //------------------------------------------------------------------ // Thread Plan accessors: //------------------------------------------------------------------ @@ -1041,6 +1046,20 @@ public: void DiscardThreadPlansUpToPlan (ThreadPlan *up_to_plan_ptr); + + //------------------------------------------------------------------ + /// Discards the plans queued on the plan stack of the current thread up to and + /// including the plan in that matches \a thread_index counting only + /// the non-Private plans. + /// + /// @param[in] up_to_plan_sp + /// Discard all plans up to and including this user plan given by this index. + /// + /// @return + /// \b true if there was a thread plan with that user index, \b false otherwise. + //------------------------------------------------------------------ + bool + DiscardUserThreadPlansUpToIndex (uint32_t thread_index); //------------------------------------------------------------------ /// Prints the current plan stack. @@ -1050,7 +1069,10 @@ public: /// //------------------------------------------------------------------ void - DumpThreadPlans (Stream *s) const; + DumpThreadPlans (Stream *s, + lldb::DescriptionLevel desc_level = lldb::eDescriptionLevelVerbose, + bool include_internal = true, + bool ignore_boring = false) const; virtual bool CheckpointThreadState (ThreadStateCheckpoint &saved_state); @@ -1293,6 +1315,7 @@ protected: lldb::ProcessWP m_process_wp; ///< The process that owns this thread. lldb::StopInfoSP m_stop_info_sp; ///< The private stop reason for this thread uint32_t m_stop_info_stop_id; // This is the stop id for which the StopInfo is valid. Can use this so you know that + uint32_t m_stop_info_override_stop_id; // The stop ID containing the last time the stop info was checked against the stop info override // the thread's m_stop_info_sp is current and you don't have to fetch it again const uint32_t m_index_id; ///< A unique 1 based index assigned to each thread for easy UI/command line access. lldb::RegisterContextSP m_reg_context_sp; ///< The register context for this thread's current register state. diff --git a/include/lldb/Target/ThreadCollection.h b/include/lldb/Target/ThreadCollection.h new file mode 100644 index 000000000000..0c2b41cc0ca4 --- /dev/null +++ b/include/lldb/Target/ThreadCollection.h @@ -0,0 +1,70 @@ +//===-- ThreadCollection.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ThreadCollection_h_ +#define liblldb_ThreadCollection_h_ + +#include + +#include "lldb/lldb-private.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Utility/Iterable.h" + +namespace lldb_private { + +class ThreadCollection +{ +public: + typedef std::vector collection; + typedef LockingAdaptedIterable ThreadIterable; + + ThreadCollection(); + + ThreadCollection(collection threads); + + virtual + ~ThreadCollection() + { + } + + uint32_t + GetSize(); + + void + AddThread (const lldb::ThreadSP &thread_sp); + + void + InsertThread (const lldb::ThreadSP &thread_sp, uint32_t idx); + + // Note that "idx" is not the same as the "thread_index". It is a zero + // based index to accessing the current threads, whereas "thread_index" + // is a unique index assigned + lldb::ThreadSP + GetThreadAtIndex (uint32_t idx); + + virtual ThreadIterable + Threads () + { + return ThreadIterable(m_threads, GetMutex()); + } + + virtual Mutex & + GetMutex() + { + return m_mutex; + } + +protected: + collection m_threads; + Mutex m_mutex; +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadCollection_h_ diff --git a/include/lldb/Target/ThreadList.h b/include/lldb/Target/ThreadList.h index 65d9b74098a6..12c430c9c8d8 100644 --- a/include/lldb/Target/ThreadList.h +++ b/include/lldb/Target/ThreadList.h @@ -15,16 +15,14 @@ #include "lldb/lldb-private.h" #include "lldb/Core/UserID.h" #include "lldb/Utility/Iterable.h" +#include "lldb/Target/ThreadCollection.h" - -// FIXME: Currently this is a thread list with lots of functionality for use only by -// the process for which this is the thread list. If we ever want a container class -// to hand out that is just a random subset of threads, with iterator functionality, -// then we should make that part a base class, and make a ProcessThreadList for the -// process. namespace lldb_private { -class ThreadList +// This is a thread list with lots of functionality for use only by the process +// for which this is the thread list. A generic container class with iterator +// functionality is ThreadCollection. +class ThreadList : public ThreadCollection { friend class Process; @@ -34,6 +32,7 @@ public: ThreadList (const ThreadList &rhs); + virtual ~ThreadList (); const ThreadList& @@ -42,11 +41,6 @@ public: uint32_t GetSize(bool can_update = true); - void - AddThread (const lldb::ThreadSP &thread_sp); - - void - InsertThread (const lldb::ThreadSP &thread_sp, uint32_t idx); // Return the selected thread if there is one. Otherwise, return the thread // selected at index 0. lldb::ThreadSP @@ -72,15 +66,6 @@ public: // is a unique index assigned lldb::ThreadSP GetThreadAtIndex (uint32_t idx, bool can_update = true); - - typedef std::vector collection; - typedef LockingAdaptedIterable ThreadIterable; - - ThreadIterable - Threads () - { - return ThreadIterable(m_threads, GetMutex()); - } lldb::ThreadSP FindThreadByID (lldb::tid_t tid, bool can_update = true); @@ -143,7 +128,7 @@ public: void SetStopID (uint32_t stop_id); - Mutex & + virtual Mutex & GetMutex (); void @@ -162,7 +147,6 @@ protected: //------------------------------------------------------------------ Process *m_process; ///< The process that manages this thread list. uint32_t m_stop_id; ///< The process stop ID that this thread list is valid for. - collection m_threads; ///< The threads for this process. lldb::tid_t m_selected_tid; ///< For targets that need the notion of a current thread. private: diff --git a/include/lldb/Target/ThreadPlan.h b/include/lldb/Target/ThreadPlan.h index 1f20841906d3..db2e79894057 100644 --- a/include/lldb/Target/ThreadPlan.h +++ b/include/lldb/Target/ThreadPlan.h @@ -223,6 +223,7 @@ namespace lldb_private { //------------------------------------------------------------------ class ThreadPlan : + public std::enable_shared_from_this, public UserID { public: @@ -241,6 +242,7 @@ public: eKindNull, eKindBase, eKindCallFunction, + eKindPython, eKindStepInstruction, eKindStepOut, eKindStepOverBreakpoint, @@ -687,7 +689,8 @@ protected: virtual lldb::StateType GetPlanRunState (); - + + DISALLOW_COPY_AND_ASSIGN(ThreadPlanNull); }; diff --git a/include/lldb/Target/ThreadPlanPython.h b/include/lldb/Target/ThreadPlanPython.h new file mode 100644 index 000000000000..fa41af1915cd --- /dev/null +++ b/include/lldb/Target/ThreadPlanPython.h @@ -0,0 +1,80 @@ +//===-- ThreadPlanPython.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ThreadPlan_Python_h_ +#define liblldb_ThreadPlan_Python_h_ + +// C Includes +// C++ Includes +#include +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/UserID.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanTracer.h" +#include "lldb/Target/StopInfo.h" + +namespace lldb_private { + +//------------------------------------------------------------------ +// ThreadPlanPython: +// +//------------------------------------------------------------------ + +class ThreadPlanPython : public ThreadPlan +{ +public: + ThreadPlanPython (Thread &thread, const char *class_name); + virtual ~ThreadPlanPython (); + + virtual void + GetDescription (Stream *s, + lldb::DescriptionLevel level); + + virtual bool + ValidatePlan (Stream *error); + + virtual bool + ShouldStop (Event *event_ptr); + + virtual bool + MischiefManaged (); + + virtual bool + WillStop (); + + virtual bool + StopOthers (); + + virtual void + DidPush (); + +protected: + virtual bool + DoPlanExplainsStop (Event *event_ptr); + + virtual lldb::StateType + GetPlanRunState (); + +private: + std::string m_class_name; + lldb::ScriptInterpreterObjectSP m_implementation_sp; + + DISALLOW_COPY_AND_ASSIGN(ThreadPlanPython); +}; + + +} // namespace lldb_private + +#endif // liblldb_ThreadPlan_Python_h_ diff --git a/include/lldb/Target/ThreadPlanStepOverBreakpoint.h b/include/lldb/Target/ThreadPlanStepOverBreakpoint.h index 41cac5c9b0b4..a4806056afb9 100644 --- a/include/lldb/Target/ThreadPlanStepOverBreakpoint.h +++ b/include/lldb/Target/ThreadPlanStepOverBreakpoint.h @@ -35,7 +35,13 @@ public: virtual void ThreadDestroyed (); void SetAutoContinue (bool do_it); virtual bool ShouldAutoContinue(Event *event_ptr); + virtual bool IsPlanStale(); + lldb::addr_t + GetBreakpointLoadAddress() const + { + return m_breakpoint_addr; + } protected: virtual bool DoPlanExplainsStop (Event *event_ptr); virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); diff --git a/include/lldb/Target/ThreadPlanStepRange.h b/include/lldb/Target/ThreadPlanStepRange.h index 3487e9ad66cb..43c55c2aa411 100644 --- a/include/lldb/Target/ThreadPlanStepRange.h +++ b/include/lldb/Target/ThreadPlanStepRange.h @@ -30,7 +30,8 @@ public: Thread &thread, const AddressRange &range, const SymbolContext &addr_context, - lldb::RunMode stop_others); + lldb::RunMode stop_others, + bool given_ranges_only = false); virtual ~ThreadPlanStepRange (); @@ -83,6 +84,7 @@ protected: bool m_first_run_event; // We want to broadcast only one running event, our first. lldb::BreakpointSP m_next_branch_bp_sp; bool m_use_fast_step; + bool m_given_ranges_only; private: std::vector m_instruction_ranges; diff --git a/include/lldb/Target/Unwind.h b/include/lldb/Target/Unwind.h index 7cda4aeb2e18..17c6c0df8207 100644 --- a/include/lldb/Target/Unwind.h +++ b/include/lldb/Target/Unwind.h @@ -27,7 +27,7 @@ protected: //------------------------------------------------------------------ Unwind(Thread &thread) : m_thread (thread), - m_unwind_mutex() + m_unwind_mutex(Mutex::eMutexTypeRecursive) { } diff --git a/include/lldb/Utility/CleanUp.h b/include/lldb/Utility/CleanUp.h index 9dd3ca5fe12b..9ffe5de27df1 100644 --- a/include/lldb/Utility/CleanUp.h +++ b/include/lldb/Utility/CleanUp.h @@ -11,6 +11,7 @@ #define liblldb_CleanUp_h_ #include "lldb/lldb-public.h" +#include namespace lldb_utility { @@ -57,7 +58,7 @@ class CleanUp { public: typedef T value_type; - typedef R (*CallbackType)(value_type); + typedef std::function CallbackType; //---------------------------------------------------------------------- // Constructor that sets the current value only. No values are @@ -188,7 +189,7 @@ class CleanUp2 { public: typedef T value_type; - typedef R (*CallbackType)(value_type, A0); + typedef std::function CallbackType; //---------------------------------------------------------------------- // Constructor that sets the current value only. No values are diff --git a/include/lldb/Utility/Iterable.h b/include/lldb/Utility/Iterable.h index 17335373e72d..17c8cf4d2319 100644 --- a/include/lldb/Utility/Iterable.h +++ b/include/lldb/Utility/Iterable.h @@ -25,6 +25,11 @@ template E vector_adapter(I &iter) return *iter; } +template E list_adapter(I &iter) +{ + return *iter; +} + template class AdaptedConstIterator { public: diff --git a/include/lldb/Utility/ProcessStructReader.h b/include/lldb/Utility/ProcessStructReader.h new file mode 100644 index 000000000000..7b05d93151aa --- /dev/null +++ b/include/lldb/Utility/ProcessStructReader.h @@ -0,0 +1,100 @@ +//===---------------------ProcessStructReader.h ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_ProcessStructReader_h_ +#define utility_ProcessStructReader_h_ + +#include "lldb/lldb-defines.h" +#include "lldb/lldb-types.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Error.h" +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Target/Process.h" + +#include +#include +#include + +namespace lldb_private { + class ProcessStructReader + { + protected: + struct FieldImpl + { + ClangASTType type; + size_t offset; + size_t size; + }; + + std::map m_fields; + DataExtractor m_data; + lldb::ByteOrder m_byte_order; + size_t m_addr_byte_size; + + public: + ProcessStructReader (Process *process, lldb::addr_t base_addr, ClangASTType struct_type) + { + if (!process) + return; + if (base_addr == 0 || base_addr == LLDB_INVALID_ADDRESS) + return; + m_byte_order = process->GetByteOrder(); + m_addr_byte_size = process->GetAddressByteSize(); + + for (size_t idx = 0; idx < struct_type.GetNumFields(); idx++) + { + std::string name; + uint64_t bit_offset; + uint32_t bitfield_bit_size; + bool is_bitfield; + ClangASTType field_type = struct_type.GetFieldAtIndex(idx,name,&bit_offset,&bitfield_bit_size,&is_bitfield); + // no support for bitfields in here (yet) + if (is_bitfield) + return; + auto size = field_type.GetByteSize(); + // no support for things larger than a uint64_t (yet) + if (size > 8) + return; + ConstString const_name = ConstString(name.c_str()); + size_t byte_index = static_cast(bit_offset / 8); + m_fields[const_name] = FieldImpl{field_type, byte_index, static_cast(size)}; + } + size_t total_size = struct_type.GetByteSize(); + lldb::DataBufferSP buffer_sp(new DataBufferHeap(total_size,0)); + Error error; + process->ReadMemoryFromInferior(base_addr, + buffer_sp->GetBytes(), + total_size, + error); + if (error.Fail()) + return; + m_data = DataExtractor(buffer_sp,m_byte_order,m_addr_byte_size); + } + + template + RetType + GetField (ConstString name, RetType fail_value = RetType()) + { + auto iter = m_fields.find(name), end = m_fields.end(); + if (iter == end) + return fail_value; + auto size = iter->second.size; + if (sizeof(RetType) < size) + return fail_value; + lldb::offset_t offset = iter->second.offset; + if (offset + size > m_data.GetByteSize()) + return fail_value; + return (RetType)(m_data.GetMaxU64(&offset, size)); + } + }; +} + +#endif // utility_ProcessStructReader_h_ diff --git a/include/lldb/Utility/RegisterNumber.h b/include/lldb/Utility/RegisterNumber.h new file mode 100644 index 000000000000..89d52fd4a967 --- /dev/null +++ b/include/lldb/Utility/RegisterNumber.h @@ -0,0 +1,69 @@ +//===-- RegisterNumber.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterNumber_h +#define liblldb_RegisterNumber_h + +#include "lldb/lldb-private.h" +#include + +//-------------------------------------------------------------------- +/// A class to represent register numbers, and able to convert between +/// different register numbering schemes that may be used in a single +/// debug session. +//-------------------------------------------------------------------- + +class RegisterNumber { +public: + RegisterNumber (lldb_private::Thread &thread, lldb::RegisterKind kind, uint32_t num); + + // This constructor plus the init() method below allow for the placeholder + // creation of an invalid object initially, possibly to be filled in. It + // would be more consistent to have three Set* methods to set the three + // data that the object needs. + RegisterNumber (); + + void + init (lldb_private::Thread &thread, lldb::RegisterKind kind, uint32_t num); + + const RegisterNumber & + operator = (const RegisterNumber &rhs); + + bool + operator == (RegisterNumber &rhs); + + bool + operator != (RegisterNumber &rhs); + + bool + IsValid () const; + + uint32_t + GetAsKind (lldb::RegisterKind kind); + + uint32_t + GetRegisterNumber () const; + + lldb::RegisterKind + GetRegisterKind () const; + + const char * + GetName (); + +private: + typedef std::map Collection; + + lldb::RegisterContextSP m_reg_ctx_sp; + uint32_t m_regnum; + lldb::RegisterKind m_kind; + Collection m_kind_regnum_map; + const char *m_name; +}; + +#endif // liblldb_RegisterNumber_h diff --git a/include/lldb/Utility/StringLexer.h b/include/lldb/Utility/StringLexer.h index 42c169c5cf94..ae6b393b0eb6 100644 --- a/include/lldb/Utility/StringLexer.h +++ b/include/lldb/Utility/StringLexer.h @@ -10,8 +10,9 @@ #ifndef utility_StringLexer_h_ #define utility_StringLexer_h_ -#include +#include #include +#include namespace lldb_utility { @@ -27,12 +28,19 @@ public: StringLexer (const StringLexer& rhs); + // These APIs are not bounds-checked. Use HasAtLeast() if you're not sure. Character Peek (); bool NextIf (Character c); + std::pair + NextIf (std::initializer_list cs); + + bool + AdvanceIf (const std::string& token); + Character Next (); @@ -42,8 +50,12 @@ public: bool HasAny (Character c); + std::string + GetUnlexed (); + + // This will assert if there are less than s characters preceding the cursor. void - PutBack (Character c); + PutBack (Size s); StringLexer& operator = (const StringLexer& rhs); @@ -51,7 +63,6 @@ public: private: std::string m_data; Position m_position; - std::list m_putback_data; void Consume(); diff --git a/include/lldb/lldb-defines.h b/include/lldb/lldb-defines.h index f8028c793233..add182c13ecb 100644 --- a/include/lldb/lldb-defines.h +++ b/include/lldb/lldb-defines.h @@ -49,7 +49,6 @@ // LLDB defines //---------------------------------------------------------------------- #define LLDB_GENERIC_ERROR UINT32_MAX -#define LLDB_DEFAULT_SHELL "/bin/sh" //---------------------------------------------------------------------- // Breakpoints diff --git a/include/lldb/lldb-enumerations.h b/include/lldb/lldb-enumerations.h index 612487fd4fad..87ee14875734 100644 --- a/include/lldb/lldb-enumerations.h +++ b/include/lldb/lldb-enumerations.h @@ -185,7 +185,8 @@ namespace lldb { eStopReasonException, eStopReasonExec, // Program was re-exec'ed eStopReasonPlanComplete, - eStopReasonThreadExiting + eStopReasonThreadExiting, + eStopReasonInstrumentation } StopReason; //---------------------------------------------------------------------- @@ -387,6 +388,11 @@ namespace lldb { eLanguageTypeDylan = 0x0020, ///< Dylan. eNumLanguageTypes } LanguageType; + + typedef enum InstrumentationRuntimeType { + eInstrumentationRuntimeTypeAddressSanitizer = 0x0000, + eNumInstrumentationRuntimeTypes + } InstrumentationRuntimeType; typedef enum DynamicValueType { @@ -414,6 +420,7 @@ namespace lldb { eArgTypeBoolean, eArgTypeBreakpointID, eArgTypeBreakpointIDRange, + eArgTypeBreakpointName, eArgTypeByteSize, eArgTypeClassName, eArgTypeCommandName, @@ -432,6 +439,7 @@ namespace lldb { eArgTypeFunctionName, eArgTypeFunctionOrSymbol, eArgTypeGDBFormat, + eArgTypeHelpText, eArgTypeIndex, eArgTypeLanguage, eArgTypeLineNum, @@ -563,6 +571,7 @@ namespace lldb { eSectionTypeELFRelocationEntries, // Elf SHT_REL or SHT_REL section eSectionTypeELFDynamicLinkInfo, // Elf SHT_DYNAMIC section eSectionTypeEHFrame, + eSectionTypeCompactUnwind, // compact unwind section in Mach-O, __TEXT,__unwind_info eSectionTypeOther } SectionType; @@ -846,9 +855,68 @@ namespace lldb { ePathTypePythonDir, // Find Python modules (PYTHONPATH) directory ePathTypeLLDBSystemPlugins, // System plug-ins directory ePathTypeLLDBUserPlugins, // User plug-ins directory - ePathTypeLLDBTempSystemDir // The LLDB temp directory for this system that will be cleaned up on exit - + ePathTypeLLDBTempSystemDir, // The LLDB temp directory for this system that will be cleaned up on exit + ePathTypeClangDir // Find path to Clang builtin headers } PathType; + + //---------------------------------------------------------------------- + // Kind of member function + // Used by the type system + //---------------------------------------------------------------------- + typedef enum MemberFunctionKind + { + eMemberFunctionKindUnknown = 0, // Not sure what the type of this is + eMemberFunctionKindConstructor, // A function used to create instances + eMemberFunctionKindDestructor, // A function used to tear down existing instances + eMemberFunctionKindInstanceMethod, // A function that applies to a specific instance + eMemberFunctionKindStaticMethod // A function that applies to a type rather than any instance + } MemberFunctionKind; + + + //---------------------------------------------------------------------- + // String matching algorithm used by SBTarget + //---------------------------------------------------------------------- + typedef enum MatchType { + eMatchTypeNormal, + eMatchTypeRegex, + eMatchTypeStartsWith + } MatchType; + + //---------------------------------------------------------------------- + // Bitmask that describes details about a type + //---------------------------------------------------------------------- + typedef enum TypeFlags { + eTypeHasChildren = (1u << 0), + eTypeHasValue = (1u << 1), + eTypeIsArray = (1u << 2), + eTypeIsBlock = (1u << 3), + eTypeIsBuiltIn = (1u << 4), + eTypeIsClass = (1u << 5), + eTypeIsCPlusPlus = (1u << 6), + eTypeIsEnumeration = (1u << 7), + eTypeIsFuncPrototype = (1u << 8), + eTypeIsMember = (1u << 9), + eTypeIsObjC = (1u << 10), + eTypeIsPointer = (1u << 11), + eTypeIsReference = (1u << 12), + eTypeIsStructUnion = (1u << 13), + eTypeIsTemplate = (1u << 14), + eTypeIsTypedef = (1u << 15), + eTypeIsVector = (1u << 16), + eTypeIsScalar = (1u << 17), + eTypeIsInteger = (1u << 18), + eTypeIsFloat = (1u << 19), + eTypeIsComplex = (1u << 20), + eTypeIsSigned = (1u << 21) + } TypeFlags; + + //---------------------------------------------------------------------- + // Whether a summary should cap how much data it returns to users or not + //---------------------------------------------------------------------- + typedef enum TypeSummaryCapping { + eTypeSummaryCapped = true, + eTypeSummaryUncapped = false + } TypeSummaryCapping; } // namespace lldb diff --git a/include/lldb/lldb-forward.h b/include/lldb/lldb-forward.h index b3d15224acb5..1ecb2f179bb2 100644 --- a/include/lldb/lldb-forward.h +++ b/include/lldb/lldb-forward.h @@ -62,9 +62,11 @@ class ClangPersistentVariables; class ClangUserExpression; class ClangUtilityFunction; class CommandInterpreter; +class CommandInterpreterRunOptions; class CommandObject; class CommandReturnObject; class Communication; +class CompactUnwindInfo; class CompileUnit; class Condition; class Connection; @@ -104,6 +106,7 @@ class FunctionInfo; class InlineFunctionInfo; class Instruction; class InstructionList; +class InstrumentationRuntime; class IOHandler; class IOObject; class IRExecutionUnit; @@ -116,6 +119,7 @@ class Log; class LogChannel; class Mangled; class Materializer; +class MemoryHistory; class Module; class ModuleList; class ModuleSpec; @@ -136,6 +140,7 @@ class OptionValueArch; class OptionValueArgs; class OptionValueArray; class OptionValueBoolean; +class OptionValueChar; class OptionValueDictionary; class OptionValueEnumeration; class OptionValueFileSpec; @@ -204,6 +209,7 @@ class StreamString; class StringList; struct StringSummaryFormat; class TypeSummaryImpl; +class TypeSummaryOptions; class Symbol; class SymbolContext; class SymbolContextList; @@ -225,6 +231,7 @@ class QueueImpl; class Target; class TargetList; class Thread; +class ThreadCollection; class ThreadList; class ThreadPlan; class ThreadPlanBase; @@ -244,10 +251,13 @@ class TypeImpl; class TypeList; class TypeListImpl; class TypeMemberImpl; +class TypeMemberFunctionImpl; class TypeEnumMemberImpl; class TypeEnumMemberListImpl; +class TypeFormatImpl; class TypeNameSpecifierImpl; class TypePair; +class TypeValidatorImpl; class UUID; class UnixSignals; class Unwind; @@ -256,7 +266,6 @@ class UnwindPlan; class UnwindTable; class VMRange; class Value; -class TypeFormatImpl; class ValueList; class ValueObject; class ValueObjectChild; @@ -308,6 +317,7 @@ namespace lldb { typedef std::shared_ptr FuncUnwindersSP; typedef std::shared_ptr InlineFunctionInfoSP; typedef std::shared_ptr InstructionSP; + typedef std::shared_ptr InstrumentationRuntimeSP; typedef std::shared_ptr IOHandlerSP; typedef std::shared_ptr IOObjectSP; typedef std::shared_ptr JITLoaderSP; @@ -316,6 +326,7 @@ namespace lldb { typedef std::shared_ptr LineTableSP; typedef std::shared_ptr ListenerSP; typedef std::shared_ptr LogChannelSP; + typedef std::shared_ptr MemoryHistorySP; typedef std::shared_ptr ModuleSP; typedef std::weak_ptr ModuleWP; typedef std::shared_ptr ObjectFileSP; @@ -361,6 +372,7 @@ namespace lldb { typedef std::shared_ptr SearchFilterSP; typedef std::shared_ptr SettingsSP; typedef std::shared_ptr StackFrameSP; + typedef std::unique_ptr StackFrameUP; typedef std::weak_ptr StackFrameWP; typedef std::shared_ptr StackFrameListSP; typedef std::shared_ptr StopInfoSP; @@ -379,17 +391,21 @@ namespace lldb { typedef std::weak_ptr TargetWP; typedef std::shared_ptr ThreadSP; typedef std::weak_ptr ThreadWP; + typedef std::shared_ptr ThreadCollectionSP; typedef std::shared_ptr ThreadPlanSP; typedef std::shared_ptr ThreadPlanTracerSP; typedef std::shared_ptr TypeSP; typedef std::weak_ptr TypeWP; typedef std::shared_ptr TypeCategoryImplSP; typedef std::shared_ptr TypeImplSP; + typedef std::shared_ptr TypeMemberFunctionImplSP; typedef std::shared_ptr TypeEnumMemberImplSP; typedef std::shared_ptr TypeFilterImplSP; typedef std::shared_ptr TypeFormatImplSP; typedef std::shared_ptr TypeNameSpecifierImplSP; typedef std::shared_ptr TypeSummaryImplSP; + typedef std::shared_ptr TypeSummaryOptionsSP; + typedef std::shared_ptr TypeValidatorImplSP; #ifndef LLDB_DISABLE_PYTHON typedef std::shared_ptr ScriptedSyntheticChildrenSP; #endif diff --git a/include/lldb/lldb-private-enumerations.h b/include/lldb/lldb-private-enumerations.h index ee1589fe24ed..c62863d744c7 100644 --- a/include/lldb/lldb-private-enumerations.h +++ b/include/lldb/lldb-private-enumerations.h @@ -22,7 +22,8 @@ typedef enum StepType eStepTypeTraceOver, ///< Single step one instruction, stepping over. eStepTypeInto, ///< Single step into a specified context. eStepTypeOver, ///< Single step over a specified context. - eStepTypeOut ///< Single step out a specified context. + eStepTypeOut, ///< Single step out a specified context. + eStepTypeScripted ///< A step type implemented by the script interpreter. } StepType; //---------------------------------------------------------------------- @@ -163,7 +164,9 @@ typedef enum FormatCategoryItem eFormatCategoryItemSynth = 0x0010, eFormatCategoryItemRegexSynth = 0x0020, eFormatCategoryItemValue = 0x0040, - eFormatCategoryItemRegexValue = 0x0080 + eFormatCategoryItemRegexValue = 0x0080, + eFormatCategoryItemValidator = 0x0100, + eFormatCategoryItemRegexValidator = 0x0200 } FormatCategoryItem; //------------------------------------------------------------------ @@ -238,6 +241,14 @@ typedef enum ExitType { eExitTypeStop, // The exit status represents the stop signal that caused the program to exit (i.e. WIFSTOPPED() was true) } ExitType; +//---------------------------------------------------------------------- +// Boolean result of running a Type Validator +//---------------------------------------------------------------------- +enum class TypeValidatorResult : bool { + Success = true, + Failure = false +}; + } // namespace lldb_private diff --git a/include/lldb/lldb-private-interfaces.h b/include/lldb/lldb-private-interfaces.h index 3251d6a9fe6c..f35938ce17b7 100644 --- a/include/lldb/lldb-private-interfaces.h +++ b/include/lldb/lldb-private-interfaces.h @@ -30,15 +30,19 @@ namespace lldb_private typedef OperatingSystem* (*OperatingSystemCreateInstance) (Process *process, bool force); typedef LanguageRuntime *(*LanguageRuntimeCreateInstance) (Process *process, lldb::LanguageType language); typedef SystemRuntime *(*SystemRuntimeCreateInstance) (Process *process); - typedef Platform* (*PlatformCreateInstance) (bool force, const ArchSpec *arch); + typedef lldb::PlatformSP (*PlatformCreateInstance) (bool force, const ArchSpec *arch); typedef lldb::ProcessSP (*ProcessCreateInstance) (Target &target, Listener &listener, const FileSpec *crash_file_path); typedef SymbolFile* (*SymbolFileCreateInstance) (ObjectFile* obj_file); typedef SymbolVendor* (*SymbolVendorCreateInstance) (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm); // Module can be NULL for default system symbol vendor typedef bool (*BreakpointHitCallback) (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id); typedef bool (*WatchpointHitCallback) (void *baton, StoppointCallbackContext *context, lldb::user_id_t watch_id); + typedef void (*OptionValueChangedCallback) (void *baton, OptionValue *option_value); typedef bool (*ThreadPlanShouldStopHereCallback) (ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation, void *baton); typedef lldb::ThreadPlanSP (*ThreadPlanStepFromHereCallback) (ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation, void *baton); typedef UnwindAssembly* (*UnwindAssemblyCreateInstance) (const ArchSpec &arch); + typedef lldb::MemoryHistorySP (*MemoryHistoryCreateInstance) (const lldb::ProcessSP &process_sp); + typedef lldb::InstrumentationRuntimeType (*InstrumentationRuntimeGetType) (); + typedef lldb::InstrumentationRuntimeSP (*InstrumentationRuntimeCreateInstance) (const lldb::ProcessSP &process_sp); typedef int (*ComparisonFunction)(const void *, const void *); typedef void (*DebuggerInitializeCallback)(Debugger &debugger); diff --git a/include/lldb/lldb-private-types.h b/include/lldb/lldb-private-types.h index 12a9324008d8..cd4867238ef9 100644 --- a/include/lldb/lldb-private-types.h +++ b/include/lldb/lldb-private-types.h @@ -29,12 +29,20 @@ namespace lldb_private const char *name; // Name of this register, can't be NULL const char *alt_name; // Alternate name of this register, can be NULL uint32_t byte_size; // Size in bytes of the register - uint32_t byte_offset; // The byte offset in the register context data where this register's value is found + uint32_t byte_offset; // The byte offset in the register context data where this register's value is found. + // This is optional, and can be 0 if a particular RegisterContext does not need to + // address its registers by byte offset. lldb::Encoding encoding; // Encoding of the register bits lldb::Format format; // Default display format uint32_t kinds[lldb::kNumRegisterKinds]; // Holds all of the various register numbers for all register kinds - uint32_t *value_regs; // List of registers that must be terminated with LLDB_INVALID_REGNUM - uint32_t *invalidate_regs; // List of registers that must be invalidated when this register is modified, list must be terminated with LLDB_INVALID_REGNUM + uint32_t *value_regs; // List of registers (terminated with LLDB_INVALID_REGNUM). If this value is not + // null, all registers in this list will be read first, at which point the value + // for this register will be valid. For example, the value list for ah + // would be eax (x86) or rax (x64). + uint32_t *invalidate_regs; // List of registers (terminated with LLDB_INVALID_REGNUM). If this value is not + // null, all registers in this list will be invalidateed when the value of this + // register changes. For example, the invalidate list for eax would be rax + // ax, ah, and al. } RegisterInfo; //---------------------------------------------------------------------- @@ -45,7 +53,11 @@ namespace lldb_private const char *name; // Name of this register set const char *short_name; // A short name for this register set size_t num_registers; // The number of registers in REGISTERS array below - const uint32_t *registers; // An array of register numbers in this set + const uint32_t *registers; // An array of register indices in this set. The values in this array are + // *indices* (not register numbers) into a particular RegisterContext's + // register array. For example, if eax is defined at index 4 for a + // particular RegisterContext, eax would be included in this RegisterSet + // by adding the value 4. Not by adding the value lldb_eax_i386. } RegisterSet; typedef struct diff --git a/include/lldb/lldb-private.h b/include/lldb/lldb-private.h index 05b2c4fd6381..bbd974303f1f 100644 --- a/include/lldb/lldb-private.h +++ b/include/lldb/lldb-private.h @@ -16,6 +16,10 @@ #include "lldb/Host/windows/win32.h" #endif +#ifdef __ANDROID_NDK__ +#include "lldb/Host/android/Android.h" +#endif + #include "lldb/lldb-public.h" #include "lldb/lldb-private-enumerations.h" #include "lldb/lldb-private-interfaces.h" diff --git a/include/lldb/lldb-types.h b/include/lldb/lldb-types.h index fee920f5b198..fe902073698d 100644 --- a/include/lldb/lldb-types.h +++ b/include/lldb/lldb-types.h @@ -50,9 +50,12 @@ namespace lldb typedef void* condition_t; typedef void* rwlock_t; typedef void* process_t; // Process type is HANDLE - typedef uintptr_t thread_t; // Host thread type + typedef void* thread_t; // Host thread type + typedef void* file_t; // Host file type + typedef void* pipe_t; // Host pipe type + typedef unsigned int __w64 socket_t; // Host socket type typedef uint32_t thread_key_t; - typedef void * thread_arg_t; // Host thread argument type + typedef void* thread_arg_t; // Host thread argument type typedef unsigned thread_result_t; // Host thread result type typedef thread_result_t (*thread_func_t)(void *); // Host thread function type } @@ -71,6 +74,9 @@ namespace lldb typedef pthread_rwlock_t rwlock_t; typedef uint64_t process_t; // Process type is just a pid. typedef pthread_t thread_t; // Host thread type + typedef int file_t; // Host file type + typedef int pipe_t; // Host pipe type + typedef int socket_t; // Host socket type typedef pthread_key_t thread_key_t; typedef void * thread_arg_t; // Host thread argument type typedef void * thread_result_t; // Host thread result type @@ -89,6 +95,7 @@ namespace lldb typedef bool (*ExpressionCancelCallback) (ExpressionEvaluationPhase phase, void *baton); } +#define LLDB_INVALID_PROCESS ((lldb::process_t)-1) #define LLDB_INVALID_HOST_THREAD ((lldb::thread_t)NULL) #define IS_VALID_LLDB_HOST_THREAD(t) ((t) != LLDB_INVALID_HOST_THREAD) diff --git a/source/API/SBAddress.cpp b/source/API/SBAddress.cpp index 6aec0722169f..d6e32b60059b 100644 --- a/source/API/SBAddress.cpp +++ b/source/API/SBAddress.cpp @@ -23,19 +23,19 @@ using namespace lldb_private; SBAddress::SBAddress () : - m_opaque_ap () + m_opaque_ap (new Address()) { } SBAddress::SBAddress (const Address *lldb_object_ptr) : - m_opaque_ap () + m_opaque_ap (new Address()) { if (lldb_object_ptr) ref() = *lldb_object_ptr; } SBAddress::SBAddress (const SBAddress &rhs) : - m_opaque_ap () + m_opaque_ap (new Address()) { if (rhs.IsValid()) ref() = rhs.ref(); @@ -49,7 +49,7 @@ SBAddress::SBAddress (lldb::SBSection section, lldb::addr_t offset) : // Create an address by resolving a load address using the supplied target SBAddress::SBAddress (lldb::addr_t load_addr, lldb::SBTarget &target) : - m_opaque_ap() + m_opaque_ap(new Address()) { SetLoadAddress (load_addr, target); } @@ -68,7 +68,7 @@ SBAddress::operator = (const SBAddress &rhs) if (rhs.IsValid()) ref() = rhs.ref(); else - m_opaque_ap.reset(); + m_opaque_ap.reset (new Address()); } return *this; } @@ -82,7 +82,7 @@ SBAddress::IsValid () const void SBAddress::Clear () { - m_opaque_ap.reset(); + m_opaque_ap.reset (new Address()); } void @@ -100,13 +100,13 @@ SBAddress::SetAddress (const Address *lldb_object_ptr) if (lldb_object_ptr) ref() = *lldb_object_ptr; else - m_opaque_ap.reset(); + m_opaque_ap.reset (new Address()); } lldb::addr_t SBAddress::GetFileAddress () const { - if (m_opaque_ap.get()) + if (m_opaque_ap->IsValid()) return m_opaque_ap->GetFileAddress(); else return LLDB_INVALID_ADDRESS; @@ -121,7 +121,7 @@ SBAddress::GetLoadAddress (const SBTarget &target) const TargetSP target_sp (target.GetSP()); if (target_sp) { - if (m_opaque_ap.get()) + if (m_opaque_ap->IsValid()) { Mutex::Locker api_locker (target_sp->GetAPIMutex()); addr = m_opaque_ap->GetLoadAddress (target_sp.get()); @@ -162,7 +162,7 @@ SBAddress::SetLoadAddress (lldb::addr_t load_addr, lldb::SBTarget &target) bool SBAddress::OffsetAddress (addr_t offset) { - if (m_opaque_ap.get()) + if (m_opaque_ap->IsValid()) { addr_t addr_offset = m_opaque_ap->GetOffset(); if (addr_offset != LLDB_INVALID_ADDRESS) @@ -178,7 +178,7 @@ lldb::SBSection SBAddress::GetSection () { lldb::SBSection sb_section; - if (m_opaque_ap.get()) + if (m_opaque_ap->IsValid()) sb_section.SetSP (m_opaque_ap->GetSection()); return sb_section; } @@ -186,7 +186,7 @@ SBAddress::GetSection () lldb::addr_t SBAddress::GetOffset () { - if (m_opaque_ap.get()) + if (m_opaque_ap->IsValid()) return m_opaque_ap->GetOffset(); return 0; } @@ -233,7 +233,7 @@ SBAddress::GetDescription (SBStream &description) // Call "ref()" on the stream to make sure it creates a backing stream in // case there isn't one already... Stream &strm = description.ref(); - if (m_opaque_ap.get()) + if (m_opaque_ap->IsValid()) { m_opaque_ap->Dump (&strm, NULL, @@ -255,7 +255,7 @@ SBModule SBAddress::GetModule () { SBModule sb_module; - if (m_opaque_ap.get()) + if (m_opaque_ap->IsValid()) sb_module.SetSP (m_opaque_ap->GetModule()); return sb_module; } @@ -264,7 +264,7 @@ SBSymbolContext SBAddress::GetSymbolContext (uint32_t resolve_scope) { SBSymbolContext sb_sc; - if (m_opaque_ap.get()) + if (m_opaque_ap->IsValid()) m_opaque_ap->CalculateSymbolContext (&sb_sc.ref(), resolve_scope); return sb_sc; } @@ -273,7 +273,7 @@ SBCompileUnit SBAddress::GetCompileUnit () { SBCompileUnit sb_comp_unit; - if (m_opaque_ap.get()) + if (m_opaque_ap->IsValid()) sb_comp_unit.reset(m_opaque_ap->CalculateSymbolContextCompileUnit()); return sb_comp_unit; } @@ -282,7 +282,7 @@ SBFunction SBAddress::GetFunction () { SBFunction sb_function; - if (m_opaque_ap.get()) + if (m_opaque_ap->IsValid()) sb_function.reset(m_opaque_ap->CalculateSymbolContextFunction()); return sb_function; } @@ -291,7 +291,7 @@ SBBlock SBAddress::GetBlock () { SBBlock sb_block; - if (m_opaque_ap.get()) + if (m_opaque_ap->IsValid()) sb_block.SetPtr(m_opaque_ap->CalculateSymbolContextBlock()); return sb_block; } @@ -300,7 +300,7 @@ SBSymbol SBAddress::GetSymbol () { SBSymbol sb_symbol; - if (m_opaque_ap.get()) + if (m_opaque_ap->IsValid()) sb_symbol.reset(m_opaque_ap->CalculateSymbolContextSymbol()); return sb_symbol; } @@ -309,7 +309,7 @@ SBLineEntry SBAddress::GetLineEntry () { SBLineEntry sb_line_entry; - if (m_opaque_ap.get()) + if (m_opaque_ap->IsValid()) { LineEntry line_entry; if (m_opaque_ap->CalculateSymbolContextLineEntry (line_entry)) @@ -321,7 +321,7 @@ SBAddress::GetLineEntry () AddressClass SBAddress::GetAddressClass () { - if (m_opaque_ap.get()) + if (m_opaque_ap->IsValid()) return m_opaque_ap->GetAddressClass(); return eAddressClassInvalid; } diff --git a/source/API/SBBreakpoint.cpp b/source/API/SBBreakpoint.cpp index a950ca934c68..dd4c80caf45d 100644 --- a/source/API/SBBreakpoint.cpp +++ b/source/API/SBBreakpoint.cpp @@ -13,6 +13,7 @@ #include "lldb/API/SBEvent.h" #include "lldb/API/SBProcess.h" #include "lldb/API/SBStream.h" +#include "lldb/API/SBStringList.h" #include "lldb/API/SBThread.h" #include "lldb/Breakpoint/Breakpoint.h" @@ -653,6 +654,83 @@ SBBreakpoint::SetScriptCallbackBody (const char *callback_body_text) return sb_error; } +bool +SBBreakpoint::AddName (const char *new_name) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + if (log) + log->Printf ("SBBreakpoint(%p)::AddName (name=%s)", + static_cast(m_opaque_sp.get()), + new_name); + + if (m_opaque_sp) + { + Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); + Error error; // Think I'm just going to swallow the error here, it's probably more annoying to have to provide it. + return m_opaque_sp->AddName(new_name, error); + } + + return false; +} + +void +SBBreakpoint::RemoveName (const char *name_to_remove) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + if (log) + log->Printf ("SBBreakpoint(%p)::RemoveName (name=%s)", + static_cast(m_opaque_sp.get()), + name_to_remove); + + if (m_opaque_sp) + { + Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); + m_opaque_sp->RemoveName(name_to_remove); + } +} + +bool +SBBreakpoint::MatchesName (const char *name) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + if (log) + log->Printf ("SBBreakpoint(%p)::MatchesName (name=%s)", + static_cast(m_opaque_sp.get()), + name); + + if (m_opaque_sp) + { + Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); + return m_opaque_sp->MatchesName(name); + } + + return false; +} + +void +SBBreakpoint::GetNames (SBStringList &names) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + if (log) + log->Printf ("SBBreakpoint(%p)::GetNames ()", + static_cast(m_opaque_sp.get())); + + if (m_opaque_sp) + { + Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); + std::vector names_vec; + m_opaque_sp->GetNames(names_vec); + for (std::string name : names_vec) + { + names.AppendString (name.c_str()); + } + } +} + lldb_private::Breakpoint * SBBreakpoint::operator->() const { diff --git a/source/API/SBCommandInterpreter.cpp b/source/API/SBCommandInterpreter.cpp index e1adea795b08..193d06e4d920 100644 --- a/source/API/SBCommandInterpreter.cpp +++ b/source/API/SBCommandInterpreter.cpp @@ -20,6 +20,7 @@ #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBCommandReturnObject.h" #include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBExecutionContext.h" #include "lldb/API/SBProcess.h" #include "lldb/API/SBTarget.h" #include "lldb/API/SBListener.h" @@ -29,6 +30,100 @@ using namespace lldb; using namespace lldb_private; +SBCommandInterpreterRunOptions::SBCommandInterpreterRunOptions() +{ + m_opaque_up.reset(new CommandInterpreterRunOptions()); +} + +SBCommandInterpreterRunOptions::~SBCommandInterpreterRunOptions() +{ + +} + +bool +SBCommandInterpreterRunOptions::GetStopOnContinue () const +{ + return m_opaque_up->GetStopOnContinue(); +} + +void +SBCommandInterpreterRunOptions::SetStopOnContinue (bool stop_on_continue) +{ + m_opaque_up->SetStopOnContinue(stop_on_continue); +} + +bool +SBCommandInterpreterRunOptions::GetStopOnError () const +{ + return m_opaque_up->GetStopOnError(); +} + +void +SBCommandInterpreterRunOptions::SetStopOnError (bool stop_on_error) +{ + m_opaque_up->SetStopOnError(stop_on_error); +} + +bool +SBCommandInterpreterRunOptions::GetStopOnCrash () const +{ + return m_opaque_up->GetStopOnCrash(); +} + +void +SBCommandInterpreterRunOptions::SetStopOnCrash (bool stop_on_crash) +{ + m_opaque_up->SetStopOnCrash(stop_on_crash); +} + +bool +SBCommandInterpreterRunOptions::GetEchoCommands () const +{ + return m_opaque_up->GetEchoCommands(); +} + +void +SBCommandInterpreterRunOptions::SetEchoCommands (bool echo_commands) +{ + m_opaque_up->SetEchoCommands(echo_commands); +} + +bool +SBCommandInterpreterRunOptions::GetPrintResults () const +{ + return m_opaque_up->GetPrintResults(); +} + +void +SBCommandInterpreterRunOptions::SetPrintResults (bool print_results) +{ + m_opaque_up->SetPrintResults(print_results); +} + +bool +SBCommandInterpreterRunOptions::GetAddToHistory () const +{ + return m_opaque_up->GetAddToHistory(); +} + +void +SBCommandInterpreterRunOptions::SetAddToHistory (bool add_to_history) +{ + m_opaque_up->SetAddToHistory(add_to_history); +} + +lldb_private::CommandInterpreterRunOptions * +SBCommandInterpreterRunOptions::get () const +{ + return m_opaque_up.get(); +} + +lldb_private::CommandInterpreterRunOptions & +SBCommandInterpreterRunOptions::ref () const +{ + return *m_opaque_up.get(); +} + class CommandPluginInterfaceImplementation : public CommandObjectParsed { public: @@ -127,6 +222,13 @@ SBCommandInterpreter::GetIOHandlerControlSequence(char ch) lldb::ReturnStatus SBCommandInterpreter::HandleCommand (const char *command_line, SBCommandReturnObject &result, bool add_to_history) +{ + SBExecutionContext sb_exe_ctx; + return HandleCommand (command_line, sb_exe_ctx, result, add_to_history); +} + +lldb::ReturnStatus +SBCommandInterpreter::HandleCommand (const char *command_line, SBExecutionContext &override_context, SBCommandReturnObject &result, bool add_to_history) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -135,11 +237,21 @@ SBCommandInterpreter::HandleCommand (const char *command_line, SBCommandReturnOb static_cast(m_opaque_ptr), command_line, static_cast(result.get()), 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 && m_opaque_ptr) { result.ref().SetInteractive(false); - m_opaque_ptr->HandleCommand (command_line, add_to_history ? eLazyBoolYes : eLazyBoolNo, result.ref()); + m_opaque_ptr->HandleCommand (command_line, add_to_history ? eLazyBoolYes : eLazyBoolNo, result.ref(), ctx_ptr); } else { @@ -162,6 +274,54 @@ SBCommandInterpreter::HandleCommand (const char *command_line, SBCommandReturnOb return result.GetStatus(); } +void +SBCommandInterpreter::HandleCommandsFromFile (lldb::SBFileSpec &file, + lldb::SBExecutionContext &override_context, + lldb::SBCommandInterpreterRunOptions &options, + lldb::SBCommandReturnObject result) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + if (log) + { + SBStream s; + file.GetDescription (s); + log->Printf ("SBCommandInterpreter(%p)::HandleCommandsFromFile (file=\"%s\", SBCommandReturnObject(%p))", + static_cast(m_opaque_ptr), s.GetData(), + static_cast(result.get())); + } + + if (!m_opaque_ptr) + { + result->AppendError ("SBCommandInterpreter is not valid."); + result->SetStatus (eReturnStatusFailed); + return; + } + + if (!file.IsValid()) + { + 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; + + + m_opaque_ptr->HandleCommandsFromFile (tmp_spec, ctx_ptr, options.ref(), result.ref()); + +} + + int SBCommandInterpreter::HandleCompletion (const char *current_line, const char *cursor, @@ -434,6 +594,7 @@ LLDBSwigPythonCallTypeScript (const char *python_function_name, void *session_dictionary, const lldb::ValueObjectSP& valobj_sp, void** pyfunct_wrapper, + const lldb::TypeSummaryOptionsSP& options_sp, std::string& retval); extern "C" void* @@ -442,6 +603,17 @@ LLDBSwigPythonCreateSyntheticProvider (const char *python_class_name, const lldb::ValueObjectSP& valobj_sp); +extern "C" void* +LLDBSwigPythonCreateScriptedThreadPlan (const char *python_class_name, + const char *session_dictionary_name, + const lldb::ThreadPlanSP& thread_plan_sp); + +extern "C" bool +LLDBSWIGPythonCallThreadPlan (void *implementor, + const char *method_name, + Event *event_sp, + bool &got_error); + extern "C" uint32_t LLDBSwigPython_CalculateNumChildren (void *implementor); @@ -463,12 +635,16 @@ LLDBSwigPython_UpdateSynthProviderInstance (void* implementor); extern "C" bool LLDBSwigPython_MightHaveChildrenSynthProviderInstance (void* implementor); +extern "C" void * +LLDBSwigPython_GetValueSynthProviderInstance (void* implementor); + extern "C" bool LLDBSwigPythonCallCommand (const char *python_function_name, const char *session_dictionary_name, lldb::DebuggerSP& debugger, const char* args, - lldb_private::CommandReturnObject &cmd_retobj); + lldb_private::CommandReturnObject &cmd_retobj, + lldb::ExecutionContextRefSP exe_ctx_ref_sp); extern "C" bool LLDBSwigPythonCallModuleInit (const char *python_module_name, @@ -504,6 +680,12 @@ LLDBSWIGPythonRunScriptKeywordFrame (const char* python_function_name, lldb::StackFrameSP& frame, std::string& output); +extern "C" bool +LLDBSWIGPythonRunScriptKeywordValue (const char* python_function_name, + const char* session_dictionary_name, + lldb::ValueObjectSP& value, + std::string& output); + extern "C" void* LLDBSWIGPython_GetDynamicSetting (void* module, const char* setting, @@ -532,6 +714,7 @@ SBCommandInterpreter::InitializeSWIG () LLDBSWIGPython_GetValueObjectSPFromSBValue, LLDBSwigPython_UpdateSynthProviderInstance, LLDBSwigPython_MightHaveChildrenSynthProviderInstance, + LLDBSwigPython_GetValueSynthProviderInstance, LLDBSwigPythonCallCommand, LLDBSwigPythonCallModuleInit, LLDBSWIGPythonCreateOSPlugin, @@ -539,7 +722,10 @@ SBCommandInterpreter::InitializeSWIG () LLDBSWIGPythonRunScriptKeywordThread, LLDBSWIGPythonRunScriptKeywordTarget, LLDBSWIGPythonRunScriptKeywordFrame, - LLDBSWIGPython_GetDynamicSetting); + LLDBSWIGPythonRunScriptKeywordValue, + LLDBSWIGPython_GetDynamicSetting, + LLDBSwigPythonCreateScriptedThreadPlan, + LLDBSWIGPythonCallThreadPlan); #endif } } diff --git a/source/API/SBCommunication.cpp b/source/API/SBCommunication.cpp index df0b864fad94..956b6cfcdd31 100644 --- a/source/API/SBCommunication.cpp +++ b/source/API/SBCommunication.cpp @@ -10,8 +10,8 @@ #include "lldb/API/SBCommunication.h" #include "lldb/API/SBBroadcaster.h" #include "lldb/Core/Communication.h" -#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/Log.h" +#include "lldb/Host/ConnectionFileDescriptor.h" using namespace lldb; using namespace lldb_private; @@ -71,7 +71,7 @@ SBCommunication::Connect (const char *url) if (m_opaque) { if (!m_opaque->HasConnection ()) - m_opaque->SetConnection (new ConnectionFileDescriptor()); + m_opaque->SetConnection(Connection::CreateDefaultConnection(url)); return m_opaque->Connect (url, NULL); } return eConnectionStatusNoConnection; diff --git a/source/API/SBCompileUnit.cpp b/source/API/SBCompileUnit.cpp index 03c25710a9e4..5d904ce56300 100644 --- a/source/API/SBCompileUnit.cpp +++ b/source/API/SBCompileUnit.cpp @@ -228,6 +228,14 @@ SBCompileUnit::FindSupportFileIndex (uint32_t start_idx, const SBFileSpec &sb_fi return 0; } +lldb::LanguageType +SBCompileUnit::GetLanguage () +{ + if (m_opaque_ptr) + return m_opaque_ptr->GetLanguage(); + return lldb::eLanguageTypeUnknown; +} + bool SBCompileUnit::IsValid () const { diff --git a/source/API/SBDebugger.cpp b/source/API/SBDebugger.cpp index dae567525a4a..a95f2ffc06d9 100644 --- a/source/API/SBDebugger.cpp +++ b/source/API/SBDebugger.cpp @@ -715,16 +715,13 @@ SBDebugger::CreateTarget (const char *filename) TargetSP target_sp; if (m_opaque_sp) { - ArchSpec arch = Target::GetDefaultArchitecture (); Error error; const bool add_dependent_modules = true; - - PlatformSP platform_sp(m_opaque_sp->GetPlatformList().GetSelectedPlatform()); - error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, + error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, filename, - arch, + NULL, add_dependent_modules, - platform_sp, + NULL, target_sp); if (error.Success()) @@ -972,7 +969,32 @@ SBDebugger::RunCommandInterpreter (bool auto_handle_events, bool spawn_thread) { if (m_opaque_sp) - m_opaque_sp->GetCommandInterpreter().RunCommandInterpreter(auto_handle_events, spawn_thread); + { + CommandInterpreterRunOptions options; + + m_opaque_sp->GetCommandInterpreter().RunCommandInterpreter(auto_handle_events, + spawn_thread, + options); + } +} + +void +SBDebugger::RunCommandInterpreter (bool auto_handle_events, + bool spawn_thread, + SBCommandInterpreterRunOptions &options, + int &num_errors, + bool &quit_requested, + bool &stopped_for_crash) + +{ + if (m_opaque_sp) + { + CommandInterpreter &interp = m_opaque_sp->GetCommandInterpreter(); + interp.RunCommandInterpreter(auto_handle_events, spawn_thread, options.ref()); + num_errors = interp.GetNumErrors(); + quit_requested = interp.GetQuitRequested(); + stopped_for_crash = interp.GetStoppedForCrash(); + } } void @@ -1186,19 +1208,42 @@ SBDebugger::GetID() SBError -SBDebugger::SetCurrentPlatform (const char *platform_name) +SBDebugger::SetCurrentPlatform (const char *platform_name_cstr) { SBError sb_error; if (m_opaque_sp) { - PlatformSP platform_sp (Platform::Create (platform_name, sb_error.ref())); - - if (platform_sp) + if (platform_name_cstr && platform_name_cstr[0]) { - bool make_selected = true; - m_opaque_sp->GetPlatformList().Append (platform_sp, make_selected); + ConstString platform_name (platform_name_cstr); + PlatformSP platform_sp (Platform::Find (platform_name)); + + if (platform_sp) + { + // Already have a platform with this name, just select it + m_opaque_sp->GetPlatformList().SetSelectedPlatform(platform_sp); + } + else + { + // We don't have a platform by this name yet, create one + platform_sp = Platform::Create (platform_name, sb_error.ref()); + if (platform_sp) + { + // We created the platform, now append and select it + bool make_selected = true; + m_opaque_sp->GetPlatformList().Append (platform_sp, make_selected); + } + } + } + else + { + sb_error.ref().SetErrorString("invalid platform name"); } } + else + { + sb_error.ref().SetErrorString("invalid debugger"); + } return sb_error; } diff --git a/source/API/SBEvent.cpp b/source/API/SBEvent.cpp index 57a699fd739d..c62c495b87c8 100644 --- a/source/API/SBEvent.cpp +++ b/source/API/SBEvent.cpp @@ -43,6 +43,12 @@ SBEvent::SBEvent (EventSP &event_sp) : { } +SBEvent::SBEvent (Event *event_ptr) : + m_event_sp (), + m_opaque_ptr (event_ptr) +{ +} + SBEvent::SBEvent (const SBEvent &rhs) : m_event_sp (rhs.m_event_sp), m_opaque_ptr (rhs.m_opaque_ptr) diff --git a/source/API/SBExecutionContext.cpp b/source/API/SBExecutionContext.cpp new file mode 100644 index 000000000000..dc20c6092132 --- /dev/null +++ b/source/API/SBExecutionContext.cpp @@ -0,0 +1,129 @@ +//===-- SBExecutionContext.cpp ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/API/SBExecutionContext.h" + +#include "lldb/API/SBTarget.h" +#include "lldb/API/SBProcess.h" +#include "lldb/API/SBThread.h" +#include "lldb/API/SBFrame.h" + +#include "lldb/Target/ExecutionContext.h" + +using namespace lldb; +using namespace lldb_private; + +SBExecutionContext::SBExecutionContext() : +m_exe_ctx_sp() +{ +} + +SBExecutionContext::SBExecutionContext (const lldb::SBExecutionContext &rhs) : +m_exe_ctx_sp(rhs.m_exe_ctx_sp) +{ +} + +SBExecutionContext::SBExecutionContext (lldb::ExecutionContextRefSP exe_ctx_ref_sp) : +m_exe_ctx_sp(exe_ctx_ref_sp) +{ +} + +SBExecutionContext::SBExecutionContext (const lldb::SBTarget &target) : +m_exe_ctx_sp(new ExecutionContextRef()) +{ + m_exe_ctx_sp->SetTargetSP(target.GetSP()); +} + +SBExecutionContext::SBExecutionContext (const lldb::SBProcess &process) : +m_exe_ctx_sp(new ExecutionContextRef()) +{ + m_exe_ctx_sp->SetProcessSP(process.GetSP()); +} + +SBExecutionContext::SBExecutionContext (lldb::SBThread thread) : +m_exe_ctx_sp(new ExecutionContextRef()) +{ + m_exe_ctx_sp->SetThreadPtr(thread.get()); +} + +SBExecutionContext::SBExecutionContext (const lldb::SBFrame &frame) : +m_exe_ctx_sp(new ExecutionContextRef()) +{ + m_exe_ctx_sp->SetFrameSP(frame.GetFrameSP()); +} + +SBExecutionContext::~SBExecutionContext() +{ +} + +const SBExecutionContext & +SBExecutionContext::operator = (const lldb::SBExecutionContext &rhs) +{ + m_exe_ctx_sp = rhs.m_exe_ctx_sp; + return *this; +} + +ExecutionContextRef * +SBExecutionContext::get () const +{ + return m_exe_ctx_sp.get(); +} + +SBTarget +SBExecutionContext::GetTarget () const +{ + SBTarget sb_target; + if (m_exe_ctx_sp) + { + TargetSP target_sp(m_exe_ctx_sp->GetTargetSP()); + if (target_sp) + sb_target.SetSP(target_sp); + } + return sb_target; +} + +SBProcess +SBExecutionContext::GetProcess () const +{ + SBProcess sb_process; + if (m_exe_ctx_sp) + { + ProcessSP process_sp(m_exe_ctx_sp->GetProcessSP()); + if (process_sp) + sb_process.SetSP(process_sp); + } + return sb_process; +} + +SBThread +SBExecutionContext::GetThread () const +{ + SBThread sb_thread; + if (m_exe_ctx_sp) + { + ThreadSP thread_sp(m_exe_ctx_sp->GetThreadSP()); + if (thread_sp) + sb_thread.SetThread(thread_sp); + } + return sb_thread; +} + +SBFrame +SBExecutionContext::GetFrame () const +{ + SBFrame sb_frame; + if (m_exe_ctx_sp) + { + StackFrameSP frame_sp(m_exe_ctx_sp->GetFrameSP()); + if (frame_sp) + sb_frame.SetFrameSP(frame_sp); + } + return sb_frame; +} + diff --git a/source/API/SBFunction.cpp b/source/API/SBFunction.cpp index 3d185da17f26..bf5e9180a437 100644 --- a/source/API/SBFunction.cpp +++ b/source/API/SBFunction.cpp @@ -227,5 +227,15 @@ SBFunction::GetBlock () return sb_block; } +lldb::LanguageType +SBFunction::GetLanguage () +{ + if (m_opaque_ptr) + { + if (m_opaque_ptr->GetCompileUnit()) + return m_opaque_ptr->GetCompileUnit()->GetLanguage(); + } + return lldb::eLanguageTypeUnknown; +} diff --git a/source/API/SBHostOS.cpp b/source/API/SBHostOS.cpp index ec1e2f2e9cba..008ca4d9672e 100644 --- a/source/API/SBHostOS.cpp +++ b/source/API/SBHostOS.cpp @@ -13,6 +13,9 @@ #include "lldb/Core/Log.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/HostNativeThread.h" +#include "lldb/Host/HostThread.h" +#include "lldb/Host/ThreadLauncher.h" using namespace lldb; using namespace lldb_private; @@ -69,31 +72,54 @@ SBHostOS::ThreadCreate // FIXME: You should log the return value? - return Host::ThreadCreate (name, thread_function, thread_arg, error_ptr ? error_ptr->get() : NULL); + HostThread thread(ThreadLauncher::LaunchThread(name, thread_function, thread_arg, error_ptr ? error_ptr->get() : NULL)); + return thread.Release(); } void SBHostOS::ThreadCreated (const char *name) { - Host::ThreadCreated (name); } bool SBHostOS::ThreadCancel (lldb::thread_t thread, SBError *error_ptr) { - return Host::ThreadCancel (thread, error_ptr ? error_ptr->get() : NULL); + Error error; + HostThread host_thread(thread); + error = host_thread.Cancel(); + if (error_ptr) + error_ptr->SetError(error); + host_thread.Release(); + return error.Success(); } bool SBHostOS::ThreadDetach (lldb::thread_t thread, SBError *error_ptr) { - return Host::ThreadDetach (thread, error_ptr ? error_ptr->get() : NULL); + Error error; +#if defined(_WIN32) + if (error_ptr) + error_ptr->SetErrorString("ThreadDetach is not supported on this platform"); +#else + HostThread host_thread(thread); + error = host_thread.GetNativeThread().Detach(); + if (error_ptr) + error_ptr->SetError(error); + host_thread.Release(); +#endif + return error.Success(); } bool SBHostOS::ThreadJoin (lldb::thread_t thread, lldb::thread_result_t *result, SBError *error_ptr) { - return Host::ThreadJoin (thread, result, error_ptr ? error_ptr->get() : NULL); + Error error; + HostThread host_thread(thread); + error = host_thread.Join(result); + if (error_ptr) + error_ptr->SetError(error); + host_thread.Release(); + return error.Success(); } diff --git a/source/API/SBInstruction.cpp b/source/API/SBInstruction.cpp index 2334cc0d124a..eccc4e29aadf 100644 --- a/source/API/SBInstruction.cpp +++ b/source/API/SBInstruction.cpp @@ -20,6 +20,7 @@ #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/EmulateInstruction.h" +#include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/StackFrame.h" @@ -170,9 +171,15 @@ SBInstruction::GetDescription (lldb::SBStream &s) { if (m_opaque_sp) { + SymbolContext sc; + const Address &addr = m_opaque_sp->GetAddress(); + ModuleSP module_sp (addr.GetModule()); + if (module_sp) + module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); // Use the "ref()" instead of the "get()" accessor in case the SBStream // didn't have a stream already created, one will get created... - m_opaque_sp->Dump (&s.ref(), 0, true, false, NULL); + const char *disassemble_format = "${addr-file-or-load}: "; + m_opaque_sp->Dump (&s.ref(), 0, true, false, NULL, &sc, NULL, disassemble_format); return true; } return false; @@ -186,8 +193,14 @@ SBInstruction::Print (FILE *out) if (m_opaque_sp) { + SymbolContext sc; + const Address &addr = m_opaque_sp->GetAddress(); + ModuleSP module_sp (addr.GetModule()); + if (module_sp) + module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); StreamFile out_stream (out, false); - m_opaque_sp->Dump (&out_stream, 0, true, false, NULL); + const char *disassemble_format = "${addr-file-or-load}: "; + m_opaque_sp->Dump (&out_stream, 0, true, false, NULL, &sc, NULL, disassemble_format); } } diff --git a/source/API/SBInstructionList.cpp b/source/API/SBInstructionList.cpp index fe22d9c29e4a..31585b3e6868 100644 --- a/source/API/SBInstructionList.cpp +++ b/source/API/SBInstructionList.cpp @@ -11,7 +11,9 @@ #include "lldb/API/SBInstruction.h" #include "lldb/API/SBStream.h" #include "lldb/Core/Disassembler.h" +#include "lldb/Core/Module.h" #include "lldb/Core/Stream.h" +#include "lldb/Symbol/SymbolContext.h" using namespace lldb; using namespace lldb_private; @@ -100,12 +102,24 @@ SBInstructionList::GetDescription (lldb::SBStream &description) // exist already inside description... Stream &sref = description.ref(); const uint32_t max_opcode_byte_size = m_opaque_sp->GetInstructionList().GetMaxOpcocdeByteSize(); + const char *disassemble_format = "${addr-file-or-load}: "; + SymbolContext sc; + SymbolContext prev_sc; for (size_t i=0; iGetInstructionList().GetInstructionAtIndex (i).get(); if (inst == NULL) break; - inst->Dump (&sref, max_opcode_byte_size, true, false, NULL); + + const Address &addr = inst->GetAddress(); + prev_sc = sc; + ModuleSP module_sp (addr.GetModule()); + if (module_sp) + { + module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); + } + + inst->Dump (&sref, max_opcode_byte_size, true, false, NULL, &sc, &prev_sc, disassemble_format); sref.EOL(); } return true; diff --git a/source/API/SBListener.cpp b/source/API/SBListener.cpp index bad9ba82bc91..87318739a3a4 100644 --- a/source/API/SBListener.cpp +++ b/source/API/SBListener.cpp @@ -69,6 +69,12 @@ SBListener::SBListener (Listener &listener) : { } +SBListener::SBListener (const lldb::ListenerSP &listener_sp) : + m_opaque_sp (listener_sp), + m_opaque_ptr (listener_sp.get()) +{ +} + SBListener::~SBListener () { } diff --git a/source/API/SBPlatform.cpp b/source/API/SBPlatform.cpp index 9914852cead7..d3e769ae675b 100644 --- a/source/API/SBPlatform.cpp +++ b/source/API/SBPlatform.cpp @@ -269,7 +269,8 @@ SBPlatform::SBPlatform (const char *platform_name) : m_opaque_sp () { Error error; - m_opaque_sp = Platform::Create (platform_name, error); + if (platform_name && platform_name[0]) + m_opaque_sp = Platform::Create (ConstString(platform_name), error); } SBPlatform::~SBPlatform() diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp index 41efd86177d6..9a0b23bc93d2 100644 --- a/source/API/SBProcess.cpp +++ b/source/API/SBProcess.cpp @@ -38,6 +38,7 @@ #include "lldb/API/SBEvent.h" #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBThread.h" +#include "lldb/API/SBThreadCollection.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBStringList.h" #include "lldb/API/SBUnixSignals.h" @@ -738,18 +739,10 @@ SBProcess::Continue () { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); - Error error (process_sp->Resume()); - if (error.Success()) - { - if (process_sp->GetTarget().GetDebugger().GetAsyncExecution () == false) - { - if (log) - log->Printf ("SBProcess(%p)::Continue () waiting for process to stop...", - static_cast(process_sp.get())); - process_sp->WaitForProcessToStop (NULL); - } - } - sb_error.SetError(error); + if (process_sp->GetTarget().GetDebugger().GetAsyncExecution ()) + sb_error.ref() = process_sp->Resume (); + else + sb_error.ref() = process_sp->ResumeSynchronous (NULL); } else sb_error.SetErrorString ("SBProcess is invalid"); @@ -1381,3 +1374,30 @@ SBProcess::GetExtendedBacktraceTypeAtIndex (uint32_t idx) } return NULL; } + +SBThreadCollection +SBProcess::GetHistoryThreads (addr_t addr) +{ + ProcessSP process_sp(GetSP()); + SBThreadCollection threads; + if (process_sp) + { + threads = SBThreadCollection(process_sp->GetHistoryThreads(addr)); + } + return threads; +} + +bool +SBProcess::IsInstrumentationRuntimePresent(InstrumentationRuntimeType type) +{ + ProcessSP process_sp(GetSP()); + if (! process_sp) + return false; + + InstrumentationRuntimeSP runtime_sp = process_sp->GetInstrumentationRuntime(type); + + if (! runtime_sp.get()) + return false; + + return runtime_sp->IsActive(); +} diff --git a/source/API/SBSection.cpp b/source/API/SBSection.cpp index 3fb84e81465c..809eca60c683 100644 --- a/source/API/SBSection.cpp +++ b/source/API/SBSection.cpp @@ -250,6 +250,14 @@ SBSection::GetSectionType () return eSectionTypeInvalid; } +uint32_t +SBSection::GetTargetByteSize () +{ + SectionSP section_sp (GetSP()); + if (section_sp.get()) + return section_sp->GetTargetByteSize(); + return 0; +} bool SBSection::operator == (const SBSection &rhs) diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp index 3d5828c5fe00..b87b1acf45df 100644 --- a/source/API/SBTarget.cpp +++ b/source/API/SBTarget.cpp @@ -58,6 +58,7 @@ #include "lldb/Interpreter/CommandReturnObject.h" #include "../source/Commands/CommandObjectBreakpoint.h" +#include "llvm/Support/Regex.h" using namespace lldb; @@ -132,6 +133,18 @@ SBLaunchInfo::SetExecutableFile (SBFileSpec exe_file, bool add_as_first_arg) m_opaque_sp->SetExecutableFile(exe_file.ref(), add_as_first_arg); } +SBListener +SBLaunchInfo::GetListener () +{ + return SBListener(m_opaque_sp->GetListener()); +} + +void +SBLaunchInfo::SetListener (SBListener &listener) +{ + m_opaque_sp->SetListener(listener.GetSP()); +} + uint32_t SBLaunchInfo::GetNumArguments () { @@ -235,13 +248,16 @@ SBLaunchInfo::SetProcessPluginName (const char *plugin_name) const char * SBLaunchInfo::GetShell () { - return m_opaque_sp->GetShell(); + // 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 shell(m_opaque_sp->GetShell().GetPath().c_str()); + return shell.AsCString(); } void SBLaunchInfo::SetShell (const char * path) { - m_opaque_sp->SetShell (path); + m_opaque_sp->SetShell (FileSpec(path, false)); } uint32_t @@ -516,6 +532,17 @@ SBAttachInfo::ParentProcessIDIsValid() return m_opaque_sp->ParentProcessIDIsValid(); } +SBListener +SBAttachInfo::GetListener () +{ + return SBListener(m_opaque_sp->GetListener()); +} + +void +SBAttachInfo::SetListener (SBListener &listener) +{ + m_opaque_sp->SetListener(listener.GetSP()); +} //---------------------------------------------------------------------- // SBTarget constructor @@ -583,6 +610,19 @@ SBTarget::GetProcess () return sb_process; } +SBPlatform +SBTarget::GetPlatform () +{ + TargetSP target_sp(GetSP()); + if (!target_sp) + return SBPlatform(); + + SBPlatform platform; + platform.m_opaque_sp = target_sp->GetPlatform(); + + return platform; +} + SBDebugger SBTarget::GetDebugger () const { @@ -734,9 +774,9 @@ SBTarget::Launch launch_info.GetEnvironmentEntries ().SetArguments (envp); if (listener.IsValid()) - error.SetError (target_sp->Launch(listener.ref(), launch_info)); - else - error.SetError (target_sp->Launch(target_sp->GetDebugger().GetListener(), launch_info)); + launch_info.SetListener(listener.GetSP()); + + error.SetError (target_sp->Launch(launch_info, NULL)); sb_process.SetSP(target_sp->GetProcessSP()); } @@ -800,7 +840,7 @@ SBTarget::Launch (SBLaunchInfo &sb_launch_info, SBError& error) if (arch_spec.IsValid()) launch_info.GetArchitecture () = arch_spec; - error.SetError (target_sp->Launch (target_sp->GetDebugger().GetListener(), launch_info)); + error.SetError (target_sp->Launch (launch_info, NULL)); sb_process.SetSP(target_sp->GetProcessSP()); } else @@ -1000,7 +1040,7 @@ SBTarget::AttachToProcessWithID // If we are doing synchronous mode, then wait for the // process to stop! if (target_sp->GetDebugger().GetAsyncExecution () == false) - process_sp->WaitForProcessToStop (NULL); + process_sp->WaitForProcessToStop (NULL); } } else @@ -1227,6 +1267,22 @@ SBTarget::ResolveLoadAddress (lldb::addr_t vm_addr) return sb_addr; } +lldb::SBAddress +SBTarget::ResolveFileAddress (lldb::addr_t file_addr) +{ + lldb::SBAddress sb_addr; + Address &addr = sb_addr.ref(); + TargetSP target_sp(GetSP()); + if (target_sp) + { + Mutex::Locker api_locker (target_sp->GetAPIMutex()); + if (target_sp->ResolveFileAddress (file_addr, addr)) + return sb_addr; + } + + addr.SetRawAddress(file_addr); + return sb_addr; +} lldb::SBAddress SBTarget::ResolvePastLoadAddress (uint32_t stop_id, lldb::addr_t vm_addr) @@ -1261,6 +1317,27 @@ SBTarget::ResolveSymbolContextForAddress (const SBAddress& addr, return sc; } +size_t +SBTarget::ReadMemory (const SBAddress addr, + void *buf, + size_t size, + lldb::SBError &error) +{ + SBError sb_error; + size_t bytes_read = 0; + TargetSP target_sp(GetSP()); + if (target_sp) + { + Mutex::Locker api_locker (target_sp->GetAPIMutex()); + bytes_read = target_sp->ReadMemory(addr.ref(), false, buf, size, sb_error.ref()); + } + else + { + sb_error.SetErrorString("invalid target"); + } + + return bytes_read; +} SBBreakpoint SBTarget::BreakpointCreateByLocation (const char *file, @@ -1868,30 +1945,10 @@ SBTarget::CreateValueFromAddress (const char *name, SBAddress addr, SBType type) lldb::ValueObjectSP new_value_sp; if (IsValid() && name && *name && addr.IsValid() && type.IsValid()) { - lldb::addr_t address(addr.GetLoadAddress(*this)); - lldb::TypeImplSP type_impl_sp (type.GetSP()); - ClangASTType pointer_ast_type(type_impl_sp->GetClangASTType(true).GetPointerType ()); - if (pointer_ast_type) - { - lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&address,sizeof(lldb::addr_t))); - - ExecutionContext exe_ctx (ExecutionContextRef(ExecutionContext(m_opaque_sp.get(),false))); - ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), - pointer_ast_type, - ConstString(name), - buffer, - exe_ctx.GetByteOrder(), - exe_ctx.GetAddressByteSize())); - - if (ptr_result_valobj_sp) - { - ptr_result_valobj_sp->GetValue().SetValueType(Value::eValueTypeLoadAddress); - Error err; - new_value_sp = ptr_result_valobj_sp->Dereference(err); - if (new_value_sp) - new_value_sp->SetName(ConstString(name)); - } - } + lldb::addr_t load_addr(addr.GetLoadAddress(*this)); + ExecutionContext exe_ctx (ExecutionContextRef(ExecutionContext(m_opaque_sp.get(),false))); + ClangASTType ast_type(type.GetSP()->GetClangASTType(true)); + new_value_sp = ValueObject::CreateValueObjectFromAddress(name, load_addr, exe_ctx, ast_type); } sb_value.SetSP(new_value_sp); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -1908,6 +1965,58 @@ SBTarget::CreateValueFromAddress (const char *name, SBAddress addr, SBType type) return sb_value; } +lldb::SBValue +SBTarget::CreateValueFromData (const char *name, lldb::SBData data, lldb::SBType type) +{ + SBValue sb_value; + lldb::ValueObjectSP new_value_sp; + if (IsValid() && name && *name && data.IsValid() && type.IsValid()) + { + DataExtractorSP extractor(*data); + ExecutionContext exe_ctx (ExecutionContextRef(ExecutionContext(m_opaque_sp.get(),false))); + ClangASTType ast_type(type.GetSP()->GetClangASTType(true)); + new_value_sp = ValueObject::CreateValueObjectFromData(name, *extractor, exe_ctx, ast_type); + } + sb_value.SetSP(new_value_sp); + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + { + if (new_value_sp) + log->Printf ("SBTarget(%p)::CreateValueFromData => \"%s\"", + static_cast(m_opaque_sp.get()), + new_value_sp->GetName().AsCString()); + else + log->Printf ("SBTarget(%p)::CreateValueFromData => NULL", + static_cast(m_opaque_sp.get())); + } + return sb_value; +} + +lldb::SBValue +SBTarget::CreateValueFromExpression (const char *name, const char* expr) +{ + SBValue sb_value; + lldb::ValueObjectSP new_value_sp; + if (IsValid() && name && *name && expr && *expr) + { + ExecutionContext exe_ctx (ExecutionContextRef(ExecutionContext(m_opaque_sp.get(),false))); + new_value_sp = ValueObject::CreateValueObjectFromExpression(name, expr, exe_ctx); + } + sb_value.SetSP(new_value_sp); + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + { + if (new_value_sp) + log->Printf ("SBTarget(%p)::CreateValueFromExpression => \"%s\"", + static_cast(m_opaque_sp.get()), + new_value_sp->GetName().AsCString()); + else + log->Printf ("SBTarget(%p)::CreateValueFromExpression => NULL", + static_cast(m_opaque_sp.get())); + } + return sb_value; +} + bool SBTarget::DeleteAllWatchpoints () { @@ -2056,6 +2165,28 @@ SBTarget::GetTriple () return NULL; } +uint32_t +SBTarget::GetDataByteSize () +{ + TargetSP target_sp(GetSP()); + if (target_sp) + { + return target_sp->GetArchitecture().GetDataByteSize() ; + } + return 0; +} + +uint32_t +SBTarget::GetCodeByteSize () +{ + TargetSP target_sp(GetSP()); + if (target_sp) + { + return target_sp->GetArchitecture().GetCodeByteSize() ; + } + return 0; +} + uint32_t SBTarget::GetAddressByteSize() { @@ -2154,6 +2285,34 @@ SBTarget::FindFunctions (const char *name, uint32_t name_type_mask) return sb_sc_list; } +lldb::SBSymbolContextList +SBTarget::FindGlobalFunctions(const char *name, uint32_t max_matches, MatchType matchtype) +{ + lldb::SBSymbolContextList sb_sc_list; + if (name && name[0]) + { + TargetSP target_sp(GetSP()); + if (target_sp) + { + std::string regexstr; + switch (matchtype) + { + case eMatchTypeRegex: + target_sp->GetImages().FindFunctions(RegularExpression(name), true, true, true, *sb_sc_list); + break; + case eMatchTypeStartsWith: + regexstr = llvm::Regex::escape(name) + ".*"; + target_sp->GetImages().FindFunctions(RegularExpression(regexstr.c_str()), true, true, true, *sb_sc_list); + break; + default: + target_sp->GetImages().FindFunctions(ConstString(name), eFunctionNameTypeAny, true, true, true, *sb_sc_list); + break; + } + } + } + return sb_sc_list; +} + lldb::SBType SBTarget::FindFirstType (const char* typename_cstr) { @@ -2188,14 +2347,19 @@ SBTarget::FindFirstType (const char* typename_cstr) if (objc_language_runtime) { - TypeVendor *objc_type_vendor = objc_language_runtime->GetTypeVendor(); + DeclVendor *objc_decl_vendor = objc_language_runtime->GetDeclVendor(); - if (objc_type_vendor) + if (objc_decl_vendor) { - std::vector types; + std::vector decls; - if (objc_type_vendor->FindTypes(const_typename, true, 1, types) > 0) - return SBType(types[0]); + if (objc_decl_vendor->FindDecls(const_typename, true, 1, decls) > 0) + { + if (ClangASTType type = ClangASTContext::GetTypeForDecl(decls[0])) + { + return SBType(type); + } + } } } } @@ -2261,17 +2425,20 @@ SBTarget::FindTypes (const char* typename_cstr) if (objc_language_runtime) { - TypeVendor *objc_type_vendor = objc_language_runtime->GetTypeVendor(); + DeclVendor *objc_decl_vendor = objc_language_runtime->GetDeclVendor(); - if (objc_type_vendor) + if (objc_decl_vendor) { - std::vector types; + std::vector decls; - if (objc_type_vendor->FindTypes(const_typename, true, UINT32_MAX, types)) + if (objc_decl_vendor->FindDecls(const_typename, true, 1, decls) > 0) { - for (ClangASTType &type : types) + for (clang::NamedDecl *decl : decls) { - sb_type_list.Append(SBType(type)); + if (ClangASTType type = ClangASTContext::GetTypeForDecl(decl)) + { + sb_type_list.Append(SBType(type)); + } } } } @@ -2321,6 +2488,61 @@ SBTarget::FindGlobalVariables (const char *name, uint32_t max_matches) return sb_value_list; } +SBValueList +SBTarget::FindGlobalVariables(const char *name, uint32_t max_matches, MatchType matchtype) +{ + SBValueList sb_value_list; + + TargetSP target_sp(GetSP()); + if (name && target_sp) + { + VariableList variable_list; + const bool append = true; + + std::string regexstr; + uint32_t match_count; + switch (matchtype) + { + case eMatchTypeNormal: + match_count = target_sp->GetImages().FindGlobalVariables(ConstString(name), + append, + max_matches, + variable_list); + break; + case eMatchTypeRegex: + match_count = target_sp->GetImages().FindGlobalVariables(RegularExpression(name), + append, + max_matches, + variable_list); + break; + case eMatchTypeStartsWith: + regexstr = llvm::Regex::escape(name) + ".*"; + match_count = target_sp->GetImages().FindGlobalVariables(RegularExpression(regexstr.c_str()), + append, + max_matches, + variable_list); + break; + } + + + if (match_count > 0) + { + ExecutionContextScope *exe_scope = target_sp->GetProcessSP().get(); + if (exe_scope == NULL) + exe_scope = target_sp.get(); + for (uint32_t i = 0; iGetStopInfo(); + StructuredData::ObjectSP info = stop_info->GetExtendedInfo(); + if (! info) + return false; + + info->Dump(strm); + + return true; +} + size_t SBThread::GetStopDescription (char *dst, size_t dst_len) { @@ -687,15 +710,11 @@ SBThread::ResumeNewPlan (ExecutionContext &exe_ctx, ThreadPlan *new_plan) // Why do we need to set the current thread by ID here??? process->GetThreadList().SetSelectedThreadByID (thread->GetID()); - sb_error.ref() = process->Resume(); - - if (sb_error.Success()) - { - // If we are doing synchronous mode, then wait for the - // process to stop yet again! - if (process->GetTarget().GetDebugger().GetAsyncExecution () == false) - process->WaitForProcessToStop (NULL); - } + + if (process->GetTarget().GetDebugger().GetAsyncExecution ()) + sb_error.ref() = process->Resume (); + else + sb_error.ref() = process->ResumeSynchronous (NULL); return sb_error; } @@ -918,7 +937,9 @@ SBThread::RunToAddress (lldb::addr_t addr) Thread *thread = exe_ctx.GetThreadPtr(); - ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads)); + ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress (abort_other_plans, + target_addr, + stop_other_threads)); // This returns an error, we should use it! ResumeNewPlan (exe_ctx, new_plan_sp.get()); @@ -1072,6 +1093,46 @@ SBThread::StepOverUntil (lldb::SBFrame &sb_frame, return sb_error; } +SBError +SBThread::StepUsingScriptedThreadPlan (const char *script_class_name) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + SBError sb_error; + + Mutex::Locker api_locker; + ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); + + if (log) + { + log->Printf ("SBThread(%p)::StepUsingScriptedThreadPlan: class name: %s", + static_cast(exe_ctx.GetThreadPtr()), + script_class_name); + } + + + if (!exe_ctx.HasThreadScope()) + { + sb_error.SetErrorString("this SBThread object is invalid"); + return sb_error; + } + + Thread *thread = exe_ctx.GetThreadPtr(); + ThreadPlanSP thread_plan_sp = thread->QueueThreadPlanForStepScripted(false, script_class_name, false); + + if (thread_plan_sp) + sb_error = ResumeNewPlan(exe_ctx, thread_plan_sp.get()); + else + { + sb_error.SetErrorStringWithFormat("Error queuing thread plan for class: %s.", script_class_name); + if (log) + log->Printf ("SBThread(%p)::StepUsingScriptedThreadPlan: Error queuing thread plan for class: %s", + static_cast(exe_ctx.GetThreadPtr()), + script_class_name); + } + + return sb_error; +} + SBError SBThread::JumpToLine (lldb::SBFileSpec &file_spec, uint32_t line) { @@ -1473,7 +1534,8 @@ SBThread::GetExtendedBacktraceThread (const char *type) const char *queue_name = new_thread_sp->GetQueueName(); if (queue_name == NULL) queue_name = ""; - log->Printf ("SBThread(%p)::GetExtendedBacktraceThread() => new extended Thread created (%p) with queue_id 0x%" PRIx64 " queue name '%s'", + log->Printf ("SBThread(%p)::GetExtendedBacktraceThread() => new extended Thread " + "created (%p) with queue_id 0x%" PRIx64 " queue name '%s'", static_cast(exe_ctx.GetThreadPtr()), static_cast(new_thread_sp.get()), new_thread_sp->GetQueueID(), @@ -1515,3 +1577,24 @@ SBThread::SafeToCallFunctions () return thread_sp->SafeToCallFunctions(); return true; } + +lldb_private::Thread * +SBThread::operator->() +{ + ThreadSP thread_sp(m_opaque_sp->GetThreadSP()); + if (thread_sp) + return thread_sp.get(); + else + return NULL; +} + +lldb_private::Thread * +SBThread::get() +{ + ThreadSP thread_sp(m_opaque_sp->GetThreadSP()); + if (thread_sp) + return thread_sp.get(); + else + return NULL; +} + diff --git a/source/API/SBThreadCollection.cpp b/source/API/SBThreadCollection.cpp new file mode 100644 index 000000000000..841f93253a53 --- /dev/null +++ b/source/API/SBThreadCollection.cpp @@ -0,0 +1,97 @@ +//===-- SBThreadCollection.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/API/SBThreadCollection.h" +#include "lldb/API/SBThread.h" +#include "lldb/Target/ThreadList.h" + +using namespace lldb; +using namespace lldb_private; + + +SBThreadCollection::SBThreadCollection () : + m_opaque_sp() +{ +} + +SBThreadCollection::SBThreadCollection(const SBThreadCollection &rhs) : + m_opaque_sp (rhs.m_opaque_sp) +{ +} + +const SBThreadCollection & +SBThreadCollection::operator = (const SBThreadCollection &rhs) +{ + if (this != &rhs) + m_opaque_sp = rhs.m_opaque_sp; + return *this; +} + +SBThreadCollection::SBThreadCollection (const ThreadCollectionSP &threads) : + m_opaque_sp(threads) +{ +} + +SBThreadCollection::~SBThreadCollection () +{ +} + +void +SBThreadCollection::SetOpaque (const lldb::ThreadCollectionSP &threads) +{ + m_opaque_sp = threads; +} + +lldb_private::ThreadCollection * +SBThreadCollection::get() const +{ + return m_opaque_sp.get(); +} + +lldb_private::ThreadCollection * +SBThreadCollection::operator->() const +{ + return m_opaque_sp.operator->(); +} + +lldb::ThreadCollectionSP & +SBThreadCollection::operator*() +{ + return m_opaque_sp; +} + +const lldb::ThreadCollectionSP & +SBThreadCollection::operator*() const +{ + return m_opaque_sp; +} + + +bool +SBThreadCollection::IsValid () const +{ + return m_opaque_sp.get() != NULL; +} + +size_t +SBThreadCollection::GetSize () +{ + if (m_opaque_sp) + return m_opaque_sp->GetSize(); + return 0; +} + +SBThread +SBThreadCollection::GetThreadAtIndex(size_t idx) +{ + SBThread thread; + if (m_opaque_sp && idx < m_opaque_sp->GetSize()) + thread = m_opaque_sp->GetThreadAtIndex(idx); + return thread; +} diff --git a/source/API/SBThreadPlan.cpp b/source/API/SBThreadPlan.cpp new file mode 100644 index 000000000000..02b1a8d893b6 --- /dev/null +++ b/source/API/SBThreadPlan.cpp @@ -0,0 +1,285 @@ +//===-- SBThread.cpp --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/lldb-python.h" + +#include "lldb/API/SBThread.h" + +#include "lldb/API/SBSymbolContext.h" +#include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBStream.h" +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/State.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StructuredData.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Target/SystemRuntime.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Queue.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanPython.h" +#include "lldb/Target/ThreadPlanStepInstruction.h" +#include "lldb/Target/ThreadPlanStepOut.h" +#include "lldb/Target/ThreadPlanStepRange.h" +#include "lldb/Target/ThreadPlanStepInRange.h" + + +#include "lldb/API/SBAddress.h" +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBEvent.h" +#include "lldb/API/SBFrame.h" +#include "lldb/API/SBProcess.h" +#include "lldb/API/SBThreadPlan.h" +#include "lldb/API/SBValue.h" + +using namespace lldb; +using namespace lldb_private; + +//---------------------------------------------------------------------- +// Constructors +//---------------------------------------------------------------------- +SBThreadPlan::SBThreadPlan () +{ +} + +SBThreadPlan::SBThreadPlan (const ThreadPlanSP& lldb_object_sp) : + m_opaque_sp (lldb_object_sp) +{ +} + +SBThreadPlan::SBThreadPlan (const SBThreadPlan &rhs) : + m_opaque_sp (rhs.m_opaque_sp) +{ + +} + +SBThreadPlan::SBThreadPlan (lldb::SBThread &sb_thread, const char *class_name) +{ + Thread *thread = sb_thread.get(); + if (thread) + m_opaque_sp.reset(new ThreadPlanPython(*thread, class_name)); +} + +//---------------------------------------------------------------------- +// Assignment operator +//---------------------------------------------------------------------- + +const lldb::SBThreadPlan & +SBThreadPlan::operator = (const SBThreadPlan &rhs) +{ + if (this != &rhs) + m_opaque_sp = rhs.m_opaque_sp; + return *this; +} +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +SBThreadPlan::~SBThreadPlan() +{ +} + +lldb_private::ThreadPlan * +SBThreadPlan::get() +{ + return m_opaque_sp.get(); +} + +bool +SBThreadPlan::IsValid() const +{ + return m_opaque_sp.get() != NULL; +} + +void +SBThreadPlan::Clear () +{ + m_opaque_sp.reset(); +} + +lldb::StopReason +SBThreadPlan::GetStopReason() +{ + return eStopReasonNone; +} + +size_t +SBThreadPlan::GetStopReasonDataCount() +{ + return 0; +} + +uint64_t +SBThreadPlan::GetStopReasonDataAtIndex(uint32_t idx) +{ + return 0; +} + +SBThread +SBThreadPlan::GetThread () const +{ + if (m_opaque_sp) + { + return SBThread(m_opaque_sp->GetThread().shared_from_this()); + } + else + return SBThread(); +} + +bool +SBThreadPlan::GetDescription (lldb::SBStream &description) const +{ + if (m_opaque_sp) + { + m_opaque_sp->GetDescription(description.get(), eDescriptionLevelFull); + } + else + { + description.Printf("Empty SBThreadPlan"); + } + return true; +} + +void +SBThreadPlan::SetThreadPlan (const ThreadPlanSP& lldb_object_sp) +{ + m_opaque_sp = lldb_object_sp; +} + +void +SBThreadPlan::SetPlanComplete (bool success) +{ + if (m_opaque_sp) + m_opaque_sp->SetPlanComplete (success); +} + +bool +SBThreadPlan::IsPlanComplete() +{ + if (m_opaque_sp) + return m_opaque_sp->IsPlanComplete(); + else + return true; +} + +bool +SBThreadPlan::IsValid() +{ + if (m_opaque_sp) + return m_opaque_sp->ValidatePlan(nullptr); + else + return false; +} + + // This section allows an SBThreadPlan to push another of the common types of plans... + // + // FIXME, you should only be able to queue thread plans from inside the methods of a + // Scripted Thread Plan. Need a way to enforce that. + +SBThreadPlan +SBThreadPlan::QueueThreadPlanForStepOverRange (SBAddress &sb_start_address, + lldb::addr_t size) +{ + if (m_opaque_sp) + { + Address *start_address = sb_start_address.get(); + if (!start_address) + { + return SBThreadPlan(); + } + + AddressRange range (*start_address, size); + SymbolContext sc; + start_address->CalculateSymbolContext(&sc); + return SBThreadPlan (m_opaque_sp->GetThread().QueueThreadPlanForStepOverRange (false, + range, + sc, + eAllThreads)); + } + else + { + return SBThreadPlan(); + } +} + +SBThreadPlan +SBThreadPlan::QueueThreadPlanForStepInRange (SBAddress &sb_start_address, + lldb::addr_t size) +{ + if (m_opaque_sp) + { + Address *start_address = sb_start_address.get(); + if (!start_address) + { + return SBThreadPlan(); + } + + AddressRange range (*start_address, size); + SymbolContext sc; + start_address->CalculateSymbolContext(&sc); + return SBThreadPlan (m_opaque_sp->GetThread().QueueThreadPlanForStepInRange (false, + range, + sc, + NULL, + eAllThreads)); + } + else + { + return SBThreadPlan(); + } +} + +SBThreadPlan +SBThreadPlan::QueueThreadPlanForStepOut (uint32_t frame_idx_to_step_to, bool first_insn) +{ + if (m_opaque_sp) + { + SymbolContext sc; + sc = m_opaque_sp->GetThread().GetStackFrameAtIndex(0)->GetSymbolContext(lldb::eSymbolContextEverything); + return SBThreadPlan (m_opaque_sp->GetThread().QueueThreadPlanForStepOut (false, + &sc, + first_insn, + false, + eVoteYes, + eVoteNoOpinion, + frame_idx_to_step_to)); + } + else + { + return SBThreadPlan(); + } +} + +SBThreadPlan +SBThreadPlan::QueueThreadPlanForRunToAddress (SBAddress sb_address) +{ + if (m_opaque_sp) + { + Address *address = sb_address.get(); + if (!address) + return SBThreadPlan(); + + return SBThreadPlan (m_opaque_sp->GetThread().QueueThreadPlanForRunToAddress (false, + *address, + false)); + } + else + { + return SBThreadPlan(); + } +} + + diff --git a/source/API/SBType.cpp b/source/API/SBType.cpp index 064fb32c953f..8a0f5d848a3d 100644 --- a/source/API/SBType.cpp +++ b/source/API/SBType.cpp @@ -155,6 +155,14 @@ SBType::IsPointerType() return m_opaque_sp->GetClangASTType(true).IsPointerType(); } +bool +SBType::IsArrayType() +{ + if (!IsValid()) + return false; + return m_opaque_sp->GetClangASTType(true).IsArrayType(nullptr, nullptr, nullptr); +} + bool SBType::IsReferenceType() { @@ -204,6 +212,14 @@ SBType::GetDereferencedType() return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetDereferencedType()))); } +SBType +SBType::GetArrayElementType() +{ + if (!IsValid()) + return SBType(); + return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetClangASTType(true).GetArrayElementType()))); +} + bool SBType::IsFunctionType () { @@ -220,7 +236,13 @@ SBType::IsPolymorphicClass () return m_opaque_sp->GetClangASTType(true).IsPolymorphicClass(); } - +bool +SBType::IsTypedefType () +{ + if (!IsValid()) + return false; + return m_opaque_sp->GetClangASTType(true).IsTypedefType(); +} lldb::SBType SBType::GetFunctionReturnType () @@ -252,6 +274,25 @@ SBType::GetFunctionArgumentTypes () return sb_type_list; } +uint32_t +SBType::GetNumberOfMemberFunctions () +{ + if (IsValid()) + { + return m_opaque_sp->GetClangASTType(true).GetNumMemberFunctions(); + } + return 0; +} + +lldb::SBTypeMemberFunction +SBType::GetMemberFunctionAtIndex (uint32_t idx) +{ + SBTypeMemberFunction sb_func_type; + if (IsValid()) + sb_func_type.reset(new TypeMemberFunctionImpl(m_opaque_sp->GetClangASTType(true).GetMemberFunctionAtIndex(idx))); + return sb_func_type; +} + lldb::SBType SBType::GetUnqualifiedType() { @@ -305,7 +346,7 @@ uint32_t SBType::GetNumberOfFields () { if (IsValid()) - return m_opaque_sp->GetClangASTType(false).GetNumFields(); + return m_opaque_sp->GetClangASTType(true).GetNumFields(); return 0; } @@ -430,6 +471,14 @@ SBType::IsTypeComplete() return m_opaque_sp->GetClangASTType(false).IsCompleteType(); } +uint32_t +SBType::GetTypeFlags () +{ + if (!IsValid()) + return 0; + return m_opaque_sp->GetClangASTType(true).GetTypeInfo(); +} + const char* SBType::GetName() { @@ -450,7 +499,7 @@ lldb::TypeClass SBType::GetTypeClass () { if (IsValid()) - return m_opaque_sp->GetClangASTType(false).GetTypeClass(); + return m_opaque_sp->GetClangASTType(true).GetTypeClass(); return lldb::eTypeClassInvalid; } @@ -684,3 +733,121 @@ SBTypeMember::ref () const { return *m_opaque_ap.get(); } + +SBTypeMemberFunction::SBTypeMemberFunction() : +m_opaque_sp() +{ +} + +SBTypeMemberFunction::~SBTypeMemberFunction() +{ +} + +SBTypeMemberFunction::SBTypeMemberFunction (const SBTypeMemberFunction& rhs) : + m_opaque_sp(rhs.m_opaque_sp) +{ +} + +lldb::SBTypeMemberFunction& +SBTypeMemberFunction::operator = (const lldb::SBTypeMemberFunction& rhs) +{ + if (this != &rhs) + m_opaque_sp = rhs.m_opaque_sp; + return *this; +} + +bool +SBTypeMemberFunction::IsValid() const +{ + return m_opaque_sp.get(); +} + +const char * +SBTypeMemberFunction::GetName () +{ + if (m_opaque_sp) + return m_opaque_sp->GetName().GetCString(); + return NULL; +} + +SBType +SBTypeMemberFunction::GetType () +{ + SBType sb_type; + if (m_opaque_sp) + { + sb_type.SetSP(lldb::TypeImplSP(new TypeImpl(m_opaque_sp->GetType()))); + } + return sb_type; +} + +lldb::SBType +SBTypeMemberFunction::GetReturnType () +{ + SBType sb_type; + if (m_opaque_sp) + { + sb_type.SetSP(lldb::TypeImplSP(new TypeImpl(m_opaque_sp->GetReturnType()))); + } + return sb_type; +} + +uint32_t +SBTypeMemberFunction::GetNumberOfArguments () +{ + if (m_opaque_sp) + return m_opaque_sp->GetNumArguments(); + return 0; +} + +lldb::SBType +SBTypeMemberFunction::GetArgumentTypeAtIndex (uint32_t i) +{ + SBType sb_type; + if (m_opaque_sp) + { + sb_type.SetSP(lldb::TypeImplSP(new TypeImpl(m_opaque_sp->GetArgumentAtIndex(i)))); + } + return sb_type; +} + +lldb::MemberFunctionKind +SBTypeMemberFunction::GetKind () +{ + if (m_opaque_sp) + return m_opaque_sp->GetKind(); + return lldb::eMemberFunctionKindUnknown; + +} + +bool +SBTypeMemberFunction::GetDescription (lldb::SBStream &description, + lldb::DescriptionLevel description_level) +{ + Stream &strm = description.ref(); + + if (m_opaque_sp) + return m_opaque_sp->GetDescription(strm); + + return false; +} + +void +SBTypeMemberFunction::reset(TypeMemberFunctionImpl *type_member_impl) +{ + m_opaque_sp.reset(type_member_impl); +} + +TypeMemberFunctionImpl & +SBTypeMemberFunction::ref () +{ + if (!m_opaque_sp) + m_opaque_sp.reset (new TypeMemberFunctionImpl()); + return *m_opaque_sp.get(); +} + +const TypeMemberFunctionImpl & +SBTypeMemberFunction::ref () const +{ + return *m_opaque_sp.get(); +} diff --git a/source/API/SBTypeSummary.cpp b/source/API/SBTypeSummary.cpp index aaa09c289cb1..8a235bf50080 100644 --- a/source/API/SBTypeSummary.cpp +++ b/source/API/SBTypeSummary.cpp @@ -20,6 +20,103 @@ using namespace lldb_private; #ifndef LLDB_DISABLE_PYTHON +SBTypeSummaryOptions::SBTypeSummaryOptions() +{ + m_opaque_ap.reset(new TypeSummaryOptions()); +} + +SBTypeSummaryOptions::SBTypeSummaryOptions (const lldb::SBTypeSummaryOptions &rhs) +{ + if (rhs.m_opaque_ap) + m_opaque_ap.reset(new TypeSummaryOptions(*rhs.m_opaque_ap.get())); + else + m_opaque_ap.reset(new TypeSummaryOptions()); +} + +SBTypeSummaryOptions::~SBTypeSummaryOptions () +{ +} + +bool +SBTypeSummaryOptions::IsValid() +{ + return m_opaque_ap.get(); +} + +lldb::LanguageType +SBTypeSummaryOptions::GetLanguage () +{ + if (IsValid()) + return m_opaque_ap->GetLanguage(); + return lldb::eLanguageTypeUnknown; +} + +lldb::TypeSummaryCapping +SBTypeSummaryOptions::GetCapping () +{ + if (IsValid()) + return m_opaque_ap->GetCapping(); + return eTypeSummaryCapped; +} + +void +SBTypeSummaryOptions::SetLanguage (lldb::LanguageType l) +{ + if (IsValid()) + m_opaque_ap->SetLanguage(l); +} + +void +SBTypeSummaryOptions::SetCapping (lldb::TypeSummaryCapping c) +{ + if (IsValid()) + m_opaque_ap->SetCapping(c); +} + +lldb_private::TypeSummaryOptions * +SBTypeSummaryOptions::operator->() +{ + return m_opaque_ap.get(); +} + +const lldb_private::TypeSummaryOptions * +SBTypeSummaryOptions::operator->() const +{ + return m_opaque_ap.get(); +} + +lldb_private::TypeSummaryOptions * +SBTypeSummaryOptions::get () +{ + return m_opaque_ap.get(); +} + +lldb_private::TypeSummaryOptions & +SBTypeSummaryOptions::ref() +{ + return *m_opaque_ap.get(); +} + +const lldb_private::TypeSummaryOptions & +SBTypeSummaryOptions::ref() const +{ + return *m_opaque_ap.get(); +} + +SBTypeSummaryOptions::SBTypeSummaryOptions (const lldb_private::TypeSummaryOptions *lldb_object_ptr) +{ + SetOptions(lldb_object_ptr); +} + +void +SBTypeSummaryOptions::SetOptions (const lldb_private::TypeSummaryOptions *lldb_object_ptr) +{ + if (lldb_object_ptr) + m_opaque_ap.reset(new TypeSummaryOptions(*lldb_object_ptr)); + else + m_opaque_ap.reset(new TypeSummaryOptions()); +} + SBTypeSummary::SBTypeSummary() : m_opaque_sp() { diff --git a/source/API/SBValue.cpp b/source/API/SBValue.cpp index 3a9621b1e3bc..0d3d7ad956ee 100644 --- a/source/API/SBValue.cpp +++ b/source/API/SBValue.cpp @@ -543,6 +543,36 @@ SBValue::GetObjectDescription () return cstr; } +const char * +SBValue::GetTypeValidatorResult () +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + const char *cstr = NULL; + ValueLocker locker; + lldb::ValueObjectSP value_sp(GetSP(locker)); + if (value_sp) + { + const auto& validation(value_sp->GetValidationStatus()); + if (TypeValidatorResult::Failure == validation.first) + { + if (validation.second.empty()) + cstr = "unknown error"; + else + cstr = validation.second.c_str(); + } + } + if (log) + { + if (cstr) + log->Printf ("SBValue(%p)::GetTypeValidatorResult() => \"%s\"", + static_cast(value_sp.get()), cstr); + else + log->Printf ("SBValue(%p)::GetTypeValidatorResult() => NULL", + static_cast(value_sp.get())); + } + return cstr; +} + SBType SBValue::GetType() { @@ -610,6 +640,32 @@ SBValue::GetSummary () } return cstr; } + +const char * +SBValue::GetSummary (lldb::SBStream& stream, + lldb::SBTypeSummaryOptions& options) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + ValueLocker locker; + lldb::ValueObjectSP value_sp(GetSP(locker)); + if (value_sp) + { + std::string buffer; + if (value_sp->GetSummaryAsCString(buffer,options.ref()) && !buffer.empty()) + stream.Printf("%s",buffer.c_str()); + } + const char* cstr = stream.GetData(); + if (log) + { + if (cstr) + log->Printf ("SBValue(%p)::GetSummary() => \"%s\"", + static_cast(value_sp.get()), cstr); + else + log->Printf ("SBValue(%p)::GetSummary() => NULL", + static_cast(value_sp.get())); + } + return cstr; +} #endif // LLDB_DISABLE_PYTHON const char * @@ -808,21 +864,11 @@ SBValue::CreateValueFromExpression (const char *name, const char *expression, SB if (value_sp) { ExecutionContext exe_ctx (value_sp->GetExecutionContextRef()); - Target* target = exe_ctx.GetTargetPtr(); - if (target) - { - options.ref().SetKeepInMemory(true); - target->EvaluateExpression (expression, - exe_ctx.GetFramePtr(), - new_value_sp, - options.ref()); - if (new_value_sp) - { - new_value_sp->SetName(ConstString(name)); - sb_value.SetSP(new_value_sp); - } - } + new_value_sp = ValueObject::CreateValueObjectFromExpression(name, expression, exe_ctx, options.ref()); + if (new_value_sp) + new_value_sp->SetName(ConstString(name)); } + sb_value.SetSP(new_value_sp); if (log) { if (new_value_sp) @@ -846,30 +892,11 @@ SBValue::CreateValueFromAddress(const char* name, lldb::addr_t address, SBType s lldb::TypeImplSP type_impl_sp (sb_type.GetSP()); if (value_sp && type_impl_sp) { - ClangASTType pointer_ast_type(type_impl_sp->GetClangASTType(false).GetPointerType ()); - if (pointer_ast_type) - { - lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&address,sizeof(lldb::addr_t))); - - ExecutionContext exe_ctx (value_sp->GetExecutionContextRef()); - ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), - pointer_ast_type, - ConstString(name), - buffer, - exe_ctx.GetByteOrder(), - exe_ctx.GetAddressByteSize())); - - if (ptr_result_valobj_sp) - { - ptr_result_valobj_sp->GetValue().SetValueType(Value::eValueTypeLoadAddress); - Error err; - new_value_sp = ptr_result_valobj_sp->Dereference(err); - if (new_value_sp) - new_value_sp->SetName(ConstString(name)); - } - sb_value.SetSP(new_value_sp); - } + ClangASTType ast_type(type_impl_sp->GetClangASTType(true)); + ExecutionContext exe_ctx (value_sp->GetExecutionContextRef()); + new_value_sp = ValueObject::CreateValueObjectFromAddress(name, address, exe_ctx, ast_type); } + sb_value.SetSP(new_value_sp); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) { @@ -894,15 +921,10 @@ SBValue::CreateValueFromData (const char* name, SBData data, SBType type) if (value_sp) { ExecutionContext exe_ctx (value_sp->GetExecutionContextRef()); - - new_value_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), - type.m_opaque_sp->GetClangASTType(false), - ConstString(name), - *data.m_opaque_sp, - LLDB_INVALID_ADDRESS); + new_value_sp = ValueObject::CreateValueObjectFromData(name, **data, exe_ctx, type.GetSP()->GetClangASTType(true)); new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad); - sb_value.SetSP(new_value_sp); } + sb_value.SetSP(new_value_sp); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) { @@ -1836,3 +1858,16 @@ SBValue::WatchPointee (bool resolve_location, bool read, bool write, SBError &er sb_watchpoint = Dereference().Watch (resolve_location, read, write, error); return sb_watchpoint; } + +lldb::SBValue +SBValue::Persist () +{ + ValueLocker locker; + lldb::ValueObjectSP value_sp(GetSP(locker)); + SBValue persisted_sb; + if (value_sp) + { + persisted_sb.SetSP(value_sp->Persist()); + } + return persisted_sb; +} diff --git a/source/API/SBValueList.cpp b/source/API/SBValueList.cpp index 5069ed3f5624..71fabe0dfc0a 100644 --- a/source/API/SBValueList.cpp +++ b/source/API/SBValueList.cpp @@ -78,6 +78,21 @@ public: } return lldb::SBValue(); } + + lldb::SBValue + GetFirstValueByName (const char* name) const + { + if (name) + { + for (auto val : m_values) + { + if (val.IsValid() && val.GetName() && + strcmp(name,val.GetName()) == 0) + return val; + } + } + return lldb::SBValue(); + } private: std::vector m_values; @@ -261,6 +276,15 @@ SBValueList::FindValueObjectByUID (lldb::user_id_t uid) return sb_value; } +SBValue +SBValueList::GetFirstValueByName (const char* name) const +{ + SBValue sb_value; + if (m_opaque_ap.get()) + sb_value = m_opaque_ap->GetFirstValueByName(name); + return sb_value; +} + void * SBValueList::opaque_ptr () { diff --git a/source/Breakpoint/Breakpoint.cpp b/source/Breakpoint/Breakpoint.cpp index 7d08170e4aed..bc269cdb95ac 100644 --- a/source/Breakpoint/Breakpoint.cpp +++ b/source/Breakpoint/Breakpoint.cpp @@ -20,11 +20,14 @@ #include "lldb/Breakpoint/BreakpointResolver.h" #include "lldb/Breakpoint/BreakpointResolverFileLine.h" #include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/SearchFilter.h" #include "lldb/Core/Section.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamString.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/Function.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadSpec.h" @@ -62,6 +65,20 @@ Breakpoint::Breakpoint(Target &target, m_being_created = false; } +Breakpoint::Breakpoint (Target &new_target, 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 (source_bp.m_options), + m_locations(*this), + m_resolve_indirect_symbols(source_bp.m_resolve_indirect_symbols) +{ + // Now go through and copy the filter & resolver: + m_resolver_sp = source_bp.m_resolver_sp->CopyForBreakpoint(*this); + m_filter_sp = source_bp.m_filter_sp->CopyForBreakpoint(*this); +} + //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- @@ -69,24 +86,16 @@ Breakpoint::~Breakpoint() { } -bool -Breakpoint::IsInternal () const -{ - return LLDB_BREAK_ID_IS_INTERNAL(m_bid); -} - - - -Target& -Breakpoint::GetTarget () +const lldb::TargetSP +Breakpoint::GetTargetSP () { - return m_target; + return m_target.shared_from_this(); } -const Target& -Breakpoint::GetTarget () const +bool +Breakpoint::IsInternal () const { - return m_target; + return LLDB_BREAK_ID_IS_INTERNAL(m_bid); } BreakpointLocationSP @@ -349,10 +358,41 @@ Breakpoint::ResolveBreakpoint () } void -Breakpoint::ResolveBreakpointInModules (ModuleList &module_list) +Breakpoint::ResolveBreakpointInModules (ModuleList &module_list, BreakpointLocationCollection &new_locations) +{ + m_locations.StartRecordingNewLocations(new_locations); + + m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list); + + m_locations.StopRecordingNewLocations(); +} + +void +Breakpoint::ResolveBreakpointInModules (ModuleList &module_list, bool send_event) { if (m_resolver_sp) - m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list); + { + // If this is not an internal breakpoint, set up to record the new locations, then dispatch + // an event with the new locations. + if (!IsInternal() && send_event) + { + BreakpointEventData *new_locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsAdded, + shared_from_this()); + + ResolveBreakpointInModules (module_list, new_locations_event->GetBreakpointLocationCollection()); + + if (new_locations_event->GetBreakpointLocationCollection().GetSize() != 0) + { + SendBreakpointChangedEvent (new_locations_event); + } + else + delete new_locations_event; + } + else + { + m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list); + } + } } void @@ -368,6 +408,11 @@ Breakpoint::ClearAllBreakpointSites () void Breakpoint::ModulesChanged (ModuleList &module_list, bool load, bool delete_locations) { + Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("Breakpoint::ModulesChanged: num_modules: %zu load: %i delete_locations: %i\n", + module_list.GetSize(), load, delete_locations); + Mutex::Locker modules_mutex(module_list.GetMutex()); if (load) { @@ -383,32 +428,27 @@ Breakpoint::ModulesChanged (ModuleList &module_list, bool load, bool delete_loca // them after the locations pass. Have to do it this way because // resolving breakpoints will add new locations potentially. - const size_t num_locs = m_locations.GetSize(); - size_t num_modules = module_list.GetSize(); - for (size_t i = 0; i < num_modules; i++) + for (ModuleSP module_sp : module_list.ModulesNoLocking()) { bool seen = false; - ModuleSP module_sp (module_list.GetModuleAtIndexUnlocked (i)); if (!m_filter_sp->ModulePasses (module_sp)) continue; - for (size_t loc_idx = 0; loc_idx < num_locs; loc_idx++) + for (BreakpointLocationSP break_loc_sp : m_locations.BreakpointLocations()) { - BreakpointLocationSP break_loc = m_locations.GetByIndex(loc_idx); - if (!break_loc->IsEnabled()) + if (!break_loc_sp->IsEnabled()) continue; - SectionSP section_sp (break_loc->GetAddress().GetSection()); + SectionSP section_sp (break_loc_sp->GetAddress().GetSection()); if (!section_sp || section_sp->GetModule() == module_sp) { if (!seen) seen = true; - if (!break_loc->ResolveBreakpointSite()) + if (!break_loc_sp->ResolveBreakpointSite()) { - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); if (log) log->Printf ("Warning: could not set breakpoint site for breakpoint location %d of breakpoint %d.\n", - break_loc->GetID(), GetID()); + break_loc_sp->GetID(), GetID()); } } } @@ -420,28 +460,7 @@ Breakpoint::ModulesChanged (ModuleList &module_list, bool load, bool delete_loca if (new_modules.GetSize() > 0) { - // If this is not an internal breakpoint, set up to record the new locations, then dispatch - // an event with the new locations. - if (!IsInternal()) - { - BreakpointEventData *new_locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsAdded, - shared_from_this()); - - m_locations.StartRecordingNewLocations(new_locations_event->GetBreakpointLocationCollection()); - - ResolveBreakpointInModules(new_modules); - - m_locations.StopRecordingNewLocations(); - if (new_locations_event->GetBreakpointLocationCollection().GetSize() != 0) - { - SendBreakpointChangedEvent (new_locations_event); - } - else - delete new_locations_event; - } - else - ResolveBreakpointInModules(new_modules); - + ResolveBreakpointInModules(new_modules); } } else @@ -498,21 +517,251 @@ Breakpoint::ModulesChanged (ModuleList &module_list, bool load, bool delete_loca } } +namespace +{ +static bool +SymbolContextsMightBeEquivalent(SymbolContext &old_sc, SymbolContext &new_sc) +{ + bool equivalent_scs = false; + + if (old_sc.module_sp.get() == new_sc.module_sp.get()) + { + // If these come from the same module, we can directly compare the pointers: + if (old_sc.comp_unit && new_sc.comp_unit + && (old_sc.comp_unit == new_sc.comp_unit)) + { + if (old_sc.function && new_sc.function + && (old_sc.function == new_sc.function)) + { + equivalent_scs = true; + } + } + else if (old_sc.symbol && new_sc.symbol + && (old_sc.symbol == new_sc.symbol)) + { + equivalent_scs = true; + } + } + else + { + // Otherwise we will compare by name... + if (old_sc.comp_unit && new_sc.comp_unit) + { + if (FileSpec::Equal(*old_sc.comp_unit, *new_sc.comp_unit, true)) + { + // Now check the functions: + if (old_sc.function && new_sc.function + && (old_sc.function->GetName() == new_sc.function->GetName())) + { + equivalent_scs = true; + } + } + } + else if (old_sc.symbol && new_sc.symbol) + { + if (Mangled::Compare(old_sc.symbol->GetMangled(), new_sc.symbol->GetMangled()) == 0) + { + equivalent_scs = true; + } + } + } + return equivalent_scs; +} +} + void Breakpoint::ModuleReplaced (ModuleSP old_module_sp, ModuleSP new_module_sp) { - ModuleList temp_list; - temp_list.Append (new_module_sp); - ModulesChanged (temp_list, true); + Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("Breakpoint::ModulesReplaced for %s\n", + old_module_sp->GetSpecificationDescription().c_str()); + // First find all the locations that are in the old module + + BreakpointLocationCollection old_break_locs; + for (BreakpointLocationSP break_loc_sp : m_locations.BreakpointLocations()) + { + SectionSP section_sp = break_loc_sp->GetAddress().GetSection(); + if (section_sp && section_sp->GetModule() == old_module_sp) + { + old_break_locs.Add(break_loc_sp); + } + } + + size_t num_old_locations = old_break_locs.GetSize(); + + if (num_old_locations == 0) + { + // There were no locations in the old module, so we just need to check if there were any in the new module. + ModuleList temp_list; + temp_list.Append (new_module_sp); + ResolveBreakpointInModules(temp_list); + } + else + { + // First search the new module for locations. + // Then compare this with the old list, copy over locations that "look the same" + // Then delete the old locations. + // Finally remember to post the creation event. + // + // Two locations are the same if they have the same comp unit & function (by name) and there are the same number + // of locations in the old function as in the new one. + + ModuleList temp_list; + temp_list.Append (new_module_sp); + BreakpointLocationCollection new_break_locs; + ResolveBreakpointInModules(temp_list, new_break_locs); + BreakpointLocationCollection locations_to_remove; + BreakpointLocationCollection locations_to_announce; + + size_t num_new_locations = new_break_locs.GetSize(); + + if (num_new_locations > 0) + { + // Break out the case of one location -> one location since that's the most common one, and there's no need + // to build up the structures needed for the merge in that case. + if (num_new_locations == 1 && num_old_locations == 1) + { + bool equivalent_locations = false; + SymbolContext old_sc, new_sc; + // The only way the old and new location can be equivalent is if they have the same amount of information: + BreakpointLocationSP old_loc_sp = old_break_locs.GetByIndex(0); + BreakpointLocationSP new_loc_sp = new_break_locs.GetByIndex(0); + + if (old_loc_sp->GetAddress().CalculateSymbolContext(&old_sc) + == new_loc_sp->GetAddress().CalculateSymbolContext(&new_sc)) + { + equivalent_locations = SymbolContextsMightBeEquivalent(old_sc, new_sc); + } + + if (equivalent_locations) + { + m_locations.SwapLocation (old_loc_sp, new_loc_sp); + } + else + { + locations_to_remove.Add(old_loc_sp); + locations_to_announce.Add(new_loc_sp); + } + } + else + { + //We don't want to have to keep computing the SymbolContexts for these addresses over and over, + // so lets get them up front: + + typedef std::map IDToSCMap; + IDToSCMap old_sc_map; + for (size_t idx = 0; idx < num_old_locations; idx++) + { + SymbolContext sc; + BreakpointLocationSP bp_loc_sp = old_break_locs.GetByIndex(idx); + lldb::break_id_t loc_id = bp_loc_sp->GetID(); + bp_loc_sp->GetAddress().CalculateSymbolContext(&old_sc_map[loc_id]); + } + + std::map new_sc_map; + for (size_t idx = 0; idx < num_new_locations; idx++) + { + SymbolContext sc; + BreakpointLocationSP bp_loc_sp = new_break_locs.GetByIndex(idx); + lldb::break_id_t loc_id = bp_loc_sp->GetID(); + bp_loc_sp->GetAddress().CalculateSymbolContext(&new_sc_map[loc_id]); + } + // Take an element from the old Symbol Contexts + while (old_sc_map.size() > 0) + { + lldb::break_id_t old_id = old_sc_map.begin()->first; + SymbolContext &old_sc = old_sc_map.begin()->second; + + // Count the number of entries equivalent to this SC for the old list: + std::vector old_id_vec; + old_id_vec.push_back(old_id); + + IDToSCMap::iterator tmp_iter; + for (tmp_iter = ++old_sc_map.begin(); tmp_iter != old_sc_map.end(); tmp_iter++) + { + if (SymbolContextsMightBeEquivalent (old_sc, tmp_iter->second)) + old_id_vec.push_back (tmp_iter->first); + } + + // Now find all the equivalent locations in the new list. + std::vector new_id_vec; + for (tmp_iter = new_sc_map.begin(); tmp_iter != new_sc_map.end(); tmp_iter++) + { + if (SymbolContextsMightBeEquivalent (old_sc, tmp_iter->second)) + new_id_vec.push_back(tmp_iter->first); + } + + // Alright, if we have the same number of potentially equivalent locations in the old + // and new modules, we'll just map them one to one in ascending ID order (assuming the + // resolver's order would match the equivalent ones. + // Otherwise, we'll dump all the old ones, and just take the new ones, erasing the elements + // from both maps as we go. + + if (old_id_vec.size() == new_id_vec.size()) + { + sort(old_id_vec.begin(), old_id_vec.end()); + sort(new_id_vec.begin(), new_id_vec.end()); + size_t num_elements = old_id_vec.size(); + for (size_t idx = 0; idx < num_elements; idx++) + { + BreakpointLocationSP old_loc_sp = old_break_locs.FindByIDPair(GetID(), old_id_vec[idx]); + BreakpointLocationSP new_loc_sp = new_break_locs.FindByIDPair(GetID(), new_id_vec[idx]); + m_locations.SwapLocation(old_loc_sp, new_loc_sp); + old_sc_map.erase(old_id_vec[idx]); + new_sc_map.erase(new_id_vec[idx]); + } + } + else + { + for (lldb::break_id_t old_id : old_id_vec) + { + locations_to_remove.Add(old_break_locs.FindByIDPair(GetID(), old_id)); + old_sc_map.erase(old_id); + } + for (lldb::break_id_t new_id : new_id_vec) + { + locations_to_announce.Add(new_break_locs.FindByIDPair(GetID(), new_id)); + new_sc_map.erase(new_id); + } + } + } + } + } + + // Now remove the remaining old locations, and cons up a removed locations event. + // Note, we don't put the new locations that were swapped with an old location on the locations_to_remove + // list, so we don't need to worry about telling the world about removing a location we didn't tell them + // about adding. + + BreakpointEventData *locations_event; + if (!IsInternal()) + locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsRemoved, + shared_from_this()); + else + locations_event = NULL; - // TO DO: For now I'm just adding locations for the new module and removing the - // breakpoint locations that were in the old module. - // We should really go find the ones that are in the new module & if we can determine that they are "equivalent" - // carry over the options from the old location to the new. + for (BreakpointLocationSP loc_sp : locations_to_remove.BreakpointLocations()) + { + m_locations.RemoveLocation(loc_sp); + if (locations_event) + locations_event->GetBreakpointLocationCollection().Add(loc_sp); + } + SendBreakpointChangedEvent (locations_event); + + // And announce the new ones. + + if (!IsInternal()) + { + locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsAdded, + shared_from_this()); + for (BreakpointLocationSP loc_sp : locations_to_announce.BreakpointLocations()) + locations_event->GetBreakpointLocationCollection().Add(loc_sp); - temp_list.Clear(); - temp_list.Append (old_module_sp); - ModulesChanged (temp_list, false, true); + SendBreakpointChangedEvent (locations_event); + } + m_locations.Compact(); + } } void @@ -534,6 +783,23 @@ Breakpoint::GetNumLocations() const return m_locations.GetSize(); } +bool +Breakpoint::AddName (const char *new_name, Error &error) +{ + if (!new_name) + return false; + if (!BreakpointID::StringIsBreakpointName(new_name, error)) + { + error.SetErrorStringWithFormat("input name \"%s\" not a breakpoint name.", new_name); + return false; + } + if (!error.Success()) + return false; + + m_name_list.insert(new_name); + return true; +} + void Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_locations) { @@ -584,6 +850,20 @@ Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_l if (level == lldb::eDescriptionLevelFull) { + if (!m_name_list.empty()) + { + s->EOL(); + s->Indent(); + s->Printf ("Names:"); + s->EOL(); + s->IndentMore(); + for (std::string name : m_name_list) + { + s->Indent(); + s->Printf("%s\n", name.c_str()); + } + s->IndentLess(); + } s->IndentLess(); s->EOL(); } diff --git a/source/Breakpoint/BreakpointID.cpp b/source/Breakpoint/BreakpointID.cpp index 9963ed68303a..31823886dd9f 100644 --- a/source/Breakpoint/BreakpointID.cpp +++ b/source/Breakpoint/BreakpointID.cpp @@ -18,6 +18,7 @@ #include "lldb/Breakpoint/BreakpointID.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Core/Stream.h" +#include "lldb/Core/Error.h" using namespace lldb; using namespace lldb_private; @@ -121,3 +122,19 @@ BreakpointID::ParseCanonicalReference (const char *input, break_id_t *break_id_p return false; } +bool +BreakpointID::StringIsBreakpointName(const char *name, Error &error) +{ + error.Clear(); + + if (name && (name[0] >= 'A' && name[0] <= 'z')) + { + if (strcspn(name, ".- ") != strlen(name)) + { + error.SetErrorStringWithFormat("invalid breakpoint name: \"%s\"", name); + } + return true; + } + else + return false; +} diff --git a/source/Breakpoint/BreakpointIDList.cpp b/source/Breakpoint/BreakpointIDList.cpp index 24101b1442fb..b8b506750b34 100644 --- a/source/Breakpoint/BreakpointIDList.cpp +++ b/source/Breakpoint/BreakpointIDList.cpp @@ -159,27 +159,52 @@ BreakpointIDList::InsertStringArray (const char **string_array, size_t array_siz // NEW_ARGS should be a copy of OLD_ARGS, with and ID range specifiers replaced by the members of the range. void -BreakpointIDList::FindAndReplaceIDRanges (Args &old_args, Target *target, CommandReturnObject &result, +BreakpointIDList::FindAndReplaceIDRanges (Args &old_args, + Target *target, + bool allow_locations, + CommandReturnObject &result, Args &new_args) { std::string range_start; const char *range_end; const char *current_arg; const size_t num_old_args = old_args.GetArgumentCount(); + std::set names_found; for (size_t i = 0; i < num_old_args; ++i) { bool is_range = false; + current_arg = old_args.GetArgumentAtIndex (i); + if (!allow_locations && strchr(current_arg, '.') != nullptr) + { + result.AppendErrorWithFormat ("Breakpoint locations not allowed, saw location: %s.", current_arg); + new_args.Clear(); + return; + } size_t range_start_len = 0; size_t range_end_pos = 0; + Error error; + if (BreakpointIDList::StringContainsIDRangeExpression (current_arg, &range_start_len, &range_end_pos)) { is_range = true; range_start.assign (current_arg, range_start_len); range_end = current_arg + range_end_pos; } + else if (BreakpointID::StringIsBreakpointName(current_arg, error)) + { + if (!error.Success()) + { + new_args.Clear(); + result.AppendError (error.AsCString()); + result.SetStatus (eReturnStatusFailed); + return; + } + else + names_found.insert(current_arg); + } else if ((i + 2 < num_old_args) && BreakpointID::IsRangeIdentifier (old_args.GetArgumentAtIndex (i+1)) && BreakpointID::IsValidIDExpression (current_arg) @@ -342,6 +367,23 @@ BreakpointIDList::FindAndReplaceIDRanges (Args &old_args, Target *target, Comman } } + // Okay, now see if we found any names, and if we did, add them: + if (target && names_found.size()) + { + for (BreakpointSP bkpt_sp : target->GetBreakpointList().Breakpoints()) + { + for (std::string name : names_found) + { + if (bkpt_sp->MatchesName(name.c_str())) + { + StreamString canonical_id_str; + BreakpointID::GetCanonicalReference (&canonical_id_str, bkpt_sp->GetID(), LLDB_INVALID_BREAK_ID); + new_args.AppendArgument (canonical_id_str.GetData()); + } + } + } + } + result.SetStatus (eReturnStatusSuccessFinishNoResult); return; } diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp index e1ac043ae905..11ecfecc5bc7 100644 --- a/source/Breakpoint/BreakpointLocation.cpp +++ b/source/Breakpoint/BreakpointLocation.cpp @@ -449,8 +449,7 @@ BreakpointLocation::ShouldStop (StoppointCallbackContext *context) bool should_stop = true; Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); - IncrementHitCount(); - + // Do this first, if a location is disabled, it shouldn't increment its hit count. if (!IsEnabled()) return false; @@ -474,6 +473,13 @@ BreakpointLocation::ShouldStop (StoppointCallbackContext *context) return should_stop; } +void +BreakpointLocation::BumpHitCount() +{ + if (IsEnabled()) + IncrementHitCount(); +} + bool BreakpointLocation::IsResolved () const { @@ -569,7 +575,7 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) s->PutCString ("re-exported target = "); else s->PutCString("where = "); - sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false); + sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false, true); } else { @@ -717,4 +723,13 @@ BreakpointLocation::SendBreakpointLocationChangedEvent (lldb::BreakpointEventTyp m_owner.GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data); } } - + +void +BreakpointLocation::SwapLocation (BreakpointLocationSP swap_from) +{ + m_address = swap_from->m_address; + m_should_resolve_indirect_functions = swap_from->m_should_resolve_indirect_functions; + m_is_reexported = swap_from->m_is_reexported; + m_is_indirect = swap_from->m_is_indirect; + m_user_expression_sp.reset(); +} diff --git a/source/Breakpoint/BreakpointLocationCollection.cpp b/source/Breakpoint/BreakpointLocationCollection.cpp index ee3f56f928d5..5756ccedfaa4 100644 --- a/source/Breakpoint/BreakpointLocationCollection.cpp +++ b/source/Breakpoint/BreakpointLocationCollection.cpp @@ -196,3 +196,4 @@ BreakpointLocationCollection::GetDescription (Stream *s, lldb::DescriptionLevel (*pos)->GetDescription(s, level); } } + diff --git a/source/Breakpoint/BreakpointLocationList.cpp b/source/Breakpoint/BreakpointLocationList.cpp index ae7f863ad090..06b270a08ce9 100644 --- a/source/Breakpoint/BreakpointLocationList.cpp +++ b/source/Breakpoint/BreakpointLocationList.cpp @@ -272,6 +272,20 @@ BreakpointLocationList::AddLocation (const Address &addr, bool resolve_indirect_ return bp_loc_sp; } +void +BreakpointLocationList::SwapLocation (BreakpointLocationSP to_location_sp, BreakpointLocationSP from_location_sp) +{ + if (!from_location_sp || !to_location_sp) + return; + + m_address_to_location.erase(to_location_sp->GetAddress()); + to_location_sp->SwapLocation(from_location_sp); + RemoveLocation(from_location_sp); + m_address_to_location[to_location_sp->GetAddress()] = to_location_sp; + to_location_sp->ResolveBreakpointSite(); +} + + bool BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp) { @@ -345,3 +359,16 @@ BreakpointLocationList::StopRecordingNewLocations () m_new_location_recorder = NULL; } +void +BreakpointLocationList::Compact() +{ + lldb::break_id_t highest_id = 0; + + for (BreakpointLocationSP loc_sp : m_locations) + { + lldb::break_id_t cur_id = loc_sp->GetID(); + if (cur_id > highest_id) + highest_id = cur_id; + } + m_next_id = highest_id; +} diff --git a/source/Breakpoint/BreakpointOptions.cpp b/source/Breakpoint/BreakpointOptions.cpp index ea8556d0930b..db76ffb8685c 100644 --- a/source/Breakpoint/BreakpointOptions.cpp +++ b/source/Breakpoint/BreakpointOptions.cpp @@ -237,8 +237,7 @@ BreakpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) cons if (m_thread_spec_ap.get()) m_thread_spec_ap->GetDescription (s, level); - else if (level == eDescriptionLevelBrief) - s->PutCString ("thread spec: no "); + if (level == lldb::eDescriptionLevelFull) { s->IndentLess(); diff --git a/source/Breakpoint/BreakpointResolverAddress.cpp b/source/Breakpoint/BreakpointResolverAddress.cpp index 1bcef93aedad..d6647130c54c 100644 --- a/source/Breakpoint/BreakpointResolverAddress.cpp +++ b/source/Breakpoint/BreakpointResolverAddress.cpp @@ -109,3 +109,11 @@ BreakpointResolverAddress::Dump (Stream *s) const { } + +lldb::BreakpointResolverSP +BreakpointResolverAddress::CopyForBreakpoint (Breakpoint &breakpoint) +{ + lldb::BreakpointResolverSP ret_sp(new BreakpointResolverAddress(&breakpoint, m_addr)); + return ret_sp; +} + diff --git a/source/Breakpoint/BreakpointResolverFileLine.cpp b/source/Breakpoint/BreakpointResolverFileLine.cpp index dcee2fd54125..950054c3d720 100644 --- a/source/Breakpoint/BreakpointResolverFileLine.cpp +++ b/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -110,3 +110,14 @@ BreakpointResolverFileLine::Dump (Stream *s) const } +lldb::BreakpointResolverSP +BreakpointResolverFileLine::CopyForBreakpoint (Breakpoint &breakpoint) +{ + lldb::BreakpointResolverSP ret_sp(new BreakpointResolverFileLine(&breakpoint, + m_file_spec, + m_line_number, + m_inlines, + m_skip_prologue)); + + return ret_sp; +} diff --git a/source/Breakpoint/BreakpointResolverFileRegex.cpp b/source/Breakpoint/BreakpointResolverFileRegex.cpp index 01aecee7b9c2..c71d9bf5ba8c 100644 --- a/source/Breakpoint/BreakpointResolverFileRegex.cpp +++ b/source/Breakpoint/BreakpointResolverFileRegex.cpp @@ -95,3 +95,10 @@ BreakpointResolverFileRegex::Dump (Stream *s) const } +lldb::BreakpointResolverSP +BreakpointResolverFileRegex::CopyForBreakpoint (Breakpoint &breakpoint) +{ + lldb::BreakpointResolverSP ret_sp(new BreakpointResolverFileRegex(&breakpoint, m_regex)); + return ret_sp; +} + diff --git a/source/Breakpoint/BreakpointResolverName.cpp b/source/Breakpoint/BreakpointResolverName.cpp index 3ac3ed06fc70..581f7b016173 100644 --- a/source/Breakpoint/BreakpointResolverName.cpp +++ b/source/Breakpoint/BreakpointResolverName.cpp @@ -121,6 +121,17 @@ BreakpointResolverName::~BreakpointResolverName () { } +BreakpointResolverName::BreakpointResolverName(const BreakpointResolverName &rhs) : + BreakpointResolver(rhs.m_breakpoint, BreakpointResolver::NameResolver), + m_lookups(rhs.m_lookups), + m_class_name(rhs.m_class_name), + m_regex(rhs.m_regex), + m_match_type (rhs.m_match_type), + m_skip_prologue (rhs.m_skip_prologue) +{ + +} + void BreakpointResolverName::AddNameLookup (const ConstString &name, uint32_t name_type_mask) { @@ -371,3 +382,10 @@ BreakpointResolverName::Dump (Stream *s) const } +lldb::BreakpointResolverSP +BreakpointResolverName::CopyForBreakpoint (Breakpoint &breakpoint) +{ + lldb::BreakpointResolverSP ret_sp(new BreakpointResolverName(*this)); + ret_sp->SetBreakpoint(&breakpoint); + return ret_sp; +} diff --git a/source/Breakpoint/BreakpointSite.cpp b/source/Breakpoint/BreakpointSite.cpp index 3cf6d37af379..469514b03f8a 100644 --- a/source/Breakpoint/BreakpointSite.cpp +++ b/source/Breakpoint/BreakpointSite.cpp @@ -199,6 +199,15 @@ BreakpointSite::ValidForThisThread (Thread *thread) return m_owners.ValidForThisThread(thread); } +void +BreakpointSite::BumpHitCounts() +{ + for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations()) + { + loc_sp->BumpHitCount(); + } +} + bool BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, lldb::addr_t *intersect_addr, size_t *intersect_size, size_t *opcode_offset) const { diff --git a/source/Commands/CommandCompletions.cpp b/source/Commands/CommandCompletions.cpp index f0ad4a896739..c65dd9d460f4 100644 --- a/source/Commands/CommandCompletions.cpp +++ b/source/Commands/CommandCompletions.cpp @@ -112,7 +112,7 @@ CommandCompletions::SourceFiles if (searcher == NULL) { lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); - SearchFilter null_searcher (target_sp); + SearchFilterForUnconstrainedSearches null_searcher (target_sp); completer.DoCompletion (&null_searcher); } else @@ -375,7 +375,7 @@ CommandCompletions::Modules if (searcher == NULL) { lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); - SearchFilter null_searcher (target_sp); + SearchFilterForUnconstrainedSearches null_searcher (target_sp); completer.DoCompletion (&null_searcher); } else @@ -406,7 +406,7 @@ CommandCompletions::Symbols if (searcher == NULL) { lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); - SearchFilter null_searcher (target_sp); + SearchFilterForUnconstrainedSearches null_searcher (target_sp); completer.DoCompletion (&null_searcher); } else diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp index 13bf1278c78c..3d4b3aff6fff 100644 --- a/source/Commands/CommandObjectBreakpoint.cpp +++ b/source/Commands/CommandObjectBreakpoint.cpp @@ -20,6 +20,8 @@ #include "lldb/Breakpoint/BreakpointIDList.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/OptionValueString.h" +#include "lldb/Interpreter/OptionValueUInt64.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/StreamString.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -145,6 +147,10 @@ public: m_condition.assign(option_arg); break; + case 'D': + m_use_dummy = true; + break; + case 'E': { LanguageType language = LanguageRuntime::GetLanguageTypeFromString (option_arg); @@ -236,6 +242,11 @@ public: m_func_name_type_mask |= eFunctionNameTypeAuto; break; + case 'N': + if (BreakpointID::StringIsBreakpointName(option_arg, error)) + m_breakpoint_names.push_back (option_arg); + break; + case 'o': m_one_shot = true; break; @@ -324,6 +335,8 @@ public: m_language = eLanguageTypeUnknown; m_skip_prologue = eLazyBoolCalculate; m_one_shot = false; + m_use_dummy = false; + m_breakpoint_names.clear(); } const OptionDefinition* @@ -343,6 +356,7 @@ public: uint32_t m_line_num; uint32_t m_column; std::vector m_func_names; + std::vector m_breakpoint_names; uint32_t m_func_name_type_mask; std::string m_func_regexp; std::string m_source_text_regexp; @@ -359,16 +373,18 @@ public: lldb::LanguageType m_language; LazyBool m_skip_prologue; bool m_one_shot; + bool m_use_dummy; }; protected: virtual bool DoExecute (Args& command, - CommandReturnObject &result) + CommandReturnObject &result) { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target == NULL) + Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); + + if (target == nullptr) { result.AppendError ("Invalid target. Must set target before setting breakpoints (see 'target create' command)."); result.SetStatus (eReturnStatusFailed); @@ -551,6 +567,13 @@ protected: if (!m_options.m_condition.empty()) bp->GetOptions()->SetCondition(m_options.m_condition.c_str()); + + if (!m_options.m_breakpoint_names.empty()) + { + Error error; // We don't need to check the error here, since the option parser checked it... + for (auto name : m_options.m_breakpoint_names) + bp->AddName(name.c_str(), error); + } bp->SetOneShot (m_options.m_one_shot); } @@ -560,10 +583,17 @@ protected: Stream &output_stream = result.GetOutputStream(); const bool show_locations = false; bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, show_locations); - // Don't print out this warning for exception breakpoints. They can get set before the target - // is set, but we won't know how to actually set the breakpoint till we run. - if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) - output_stream.Printf ("WARNING: Unable to resolve breakpoint to any actual locations.\n"); + if (target == m_interpreter.GetDebugger().GetDummyTarget()) + output_stream.Printf ("Breakpoint set in dummy target, will get copied into future targets.\n"); + else + { + // Don't print out this warning for exception breakpoints. They can get set before the target + // is set, but we won't know how to actually set the breakpoint till we run. + if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) + { + output_stream.Printf ("WARNING: Unable to resolve breakpoint to any actual locations.\n"); + } + } result.SetStatus (eReturnStatusSuccessFinishResult); } else if (!bp) @@ -709,6 +739,12 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] = { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. If not set the target.skip-prologue setting is used." }, + { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, + "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, + + { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBreakpointName, + "Adds this to the list of names for this breakopint."}, + { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; @@ -766,7 +802,8 @@ public: m_name_passed (false), m_queue_passed (false), m_condition_passed (false), - m_one_shot_passed (false) + m_one_shot_passed (false), + m_use_dummy (false) { } @@ -792,6 +829,9 @@ public: m_enable_passed = true; m_enable_value = false; break; + case 'D': + m_use_dummy = true; + break; case 'e': m_enable_passed = true; m_enable_value = true; @@ -888,6 +928,7 @@ public: m_name_passed = false; m_condition_passed = false; m_one_shot_passed = false; + m_use_dummy = false; } const OptionDefinition* @@ -918,6 +959,7 @@ public: bool m_queue_passed; bool m_condition_passed; bool m_one_shot_passed; + bool m_use_dummy; }; @@ -925,7 +967,7 @@ protected: virtual bool DoExecute (Args& command, CommandReturnObject &result) { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); if (target == NULL) { result.AppendError ("Invalid target. No existing target or breakpoints."); @@ -938,7 +980,7 @@ protected: BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); if (result.Succeeded()) { @@ -1024,6 +1066,8 @@ CommandObjectBreakpointModify::CommandOptions::g_option_table[] = { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."}, { LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Enable the breakpoint."}, { LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Disable the breakpoint."}, +{ LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, + { 0, false, NULL, 0 , 0, NULL, NULL, 0, eArgTypeNone, NULL } }; @@ -1055,7 +1099,7 @@ protected: virtual bool DoExecute (Args& command, CommandReturnObject &result) { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + Target *target = GetSelectedOrDummyTarget(); if (target == NULL) { result.AppendError ("Invalid target. No existing target or breakpoints."); @@ -1088,7 +1132,7 @@ protected: { // Particular breakpoint selected; enable that breakpoint. BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); if (result.Succeeded()) { @@ -1175,7 +1219,7 @@ protected: virtual bool DoExecute (Args& command, CommandReturnObject &result) { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + Target *target = GetSelectedOrDummyTarget(); if (target == NULL) { result.AppendError ("Invalid target. No existing target or breakpoints."); @@ -1208,7 +1252,7 @@ protected: // Particular breakpoint selected; disable that breakpoint. BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); if (result.Succeeded()) { @@ -1293,7 +1337,8 @@ public: CommandOptions (CommandInterpreter &interpreter) : Options (interpreter), - m_level (lldb::eDescriptionLevelBrief) // Breakpoint List defaults to brief descriptions + m_level (lldb::eDescriptionLevelBrief), + m_use_dummy(false) { } @@ -1311,6 +1356,9 @@ public: case 'b': m_level = lldb::eDescriptionLevelBrief; break; + case 'D': + m_use_dummy = true; + break; case 'f': m_level = lldb::eDescriptionLevelFull; break; @@ -1333,6 +1381,7 @@ public: { m_level = lldb::eDescriptionLevelFull; m_internal = false; + m_use_dummy = false; } const OptionDefinition * @@ -1350,13 +1399,15 @@ public: lldb::DescriptionLevel m_level; bool m_internal; + bool m_use_dummy; }; protected: virtual bool DoExecute (Args& command, CommandReturnObject &result) { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); + if (target == NULL) { result.AppendError ("Invalid target. No current target or breakpoints."); @@ -1394,7 +1445,7 @@ protected: { // Particular breakpoints selected; show info about that breakpoint. BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); if (result.Succeeded()) { @@ -1438,6 +1489,9 @@ CommandObjectBreakpointList::CommandOptions::g_option_table[] = { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." }, + { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, + "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, + { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; @@ -1540,7 +1594,7 @@ protected: virtual bool DoExecute (Args& command, CommandReturnObject &result) { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + Target *target = GetSelectedOrDummyTarget(); if (target == NULL) { result.AppendError ("Invalid target. No existing target or breakpoints."); @@ -1656,7 +1710,8 @@ public: CommandObjectParsed (interpreter, "breakpoint delete", "Delete the specified breakpoint(s). If no breakpoints are specified, delete them all.", - NULL) + NULL), + m_options (interpreter) { CommandArgumentEntry arg; CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange); @@ -1667,11 +1722,78 @@ public: virtual ~CommandObjectBreakpointDelete () {} + virtual Options * + GetOptions () + { + return &m_options; + } + + class CommandOptions : public Options + { + public: + + CommandOptions (CommandInterpreter &interpreter) : + Options (interpreter), + m_use_dummy (false), + m_force (false) + { + } + + virtual + ~CommandOptions () {} + + virtual Error + SetOptionValue (uint32_t option_idx, const char *option_arg) + { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) + { + case 'f': + m_force = true; + break; + + case 'D': + m_use_dummy = true; + break; + + default: + error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); + break; + } + + return error; + } + + void + OptionParsingStarting () + { + m_use_dummy = false; + m_force = false; + } + + const OptionDefinition* + GetDefinitions () + { + return g_option_table; + } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + bool m_use_dummy; + bool m_force; + }; + protected: virtual bool DoExecute (Args& command, CommandReturnObject &result) { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); + if (target == NULL) { result.AppendError ("Invalid target. No existing target or breakpoints."); @@ -1695,7 +1817,7 @@ protected: if (command.GetArgumentCount() == 0) { - if (!m_interpreter.Confirm ("About to delete all breakpoints, do you want to do that?", true)) + if (!m_options.m_force && !m_interpreter.Confirm ("About to delete all breakpoints, do you want to do that?", true)) { result.AppendMessage("Operation cancelled..."); } @@ -1710,7 +1832,7 @@ protected: { // Particular breakpoint selected; disable that breakpoint. BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); if (result.Succeeded()) { @@ -1748,7 +1870,416 @@ protected: } return result.Succeeded(); } +private: + CommandOptions m_options; +}; + +OptionDefinition +CommandObjectBreakpointDelete::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, + "Delete all breakpoints without querying for confirmation."}, + + { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, + "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, + + { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } +}; + +//------------------------------------------------------------------------- +// CommandObjectBreakpointName +//------------------------------------------------------------------------- + +static OptionDefinition +g_breakpoint_name_options[] = +{ + { LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, + { LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBreakpointID, "Specify a breakpoint id to use."}, + { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, + "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, }; +class BreakpointNameOptionGroup : public OptionGroup +{ +public: + BreakpointNameOptionGroup() : + OptionGroup(), + m_breakpoint(LLDB_INVALID_BREAK_ID), + m_use_dummy (false) + { + + } + + virtual + ~BreakpointNameOptionGroup () + { + } + + virtual uint32_t + GetNumDefinitions () + { + return sizeof (g_breakpoint_name_options) / sizeof (OptionDefinition); + } + + virtual const OptionDefinition* + GetDefinitions () + { + return g_breakpoint_name_options; + } + + virtual Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) + { + Error error; + const int short_option = g_breakpoint_name_options[option_idx].short_option; + + switch (short_option) + { + case 'N': + if (BreakpointID::StringIsBreakpointName(option_value, error) && error.Success()) + m_name.SetValueFromCString(option_value); + break; + + case 'B': + if (m_breakpoint.SetValueFromCString(option_value).Fail()) + error.SetErrorStringWithFormat ("unrecognized value \"%s\" for breakpoint", option_value); + break; + case 'D': + if (m_use_dummy.SetValueFromCString(option_value).Fail()) + error.SetErrorStringWithFormat ("unrecognized value \"%s\" for use-dummy", option_value); + break; + + default: + error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); + break; + } + return error; + } + + virtual void + OptionParsingStarting (CommandInterpreter &interpreter) + { + m_name.Clear(); + m_breakpoint.Clear(); + m_use_dummy.Clear(); + m_use_dummy.SetDefaultValue(false); + } + + OptionValueString m_name; + OptionValueUInt64 m_breakpoint; + OptionValueBoolean m_use_dummy; +}; + + +class CommandObjectBreakpointNameAdd : public CommandObjectParsed +{ +public: + CommandObjectBreakpointNameAdd (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "add", + "Add a name to the breakpoints provided.", + "breakpoint name add "), + m_name_options(), + m_option_group(interpreter) + { + // Create the first variant for the first (and only) argument for this command. + CommandArgumentEntry arg1; + CommandArgumentData id_arg; + id_arg.arg_type = eArgTypeBreakpointID; + id_arg.arg_repetition = eArgRepeatOptional; + arg1.push_back(id_arg); + m_arguments.push_back (arg1); + + m_option_group.Append (&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); + m_option_group.Finalize(); + } + + virtual + ~CommandObjectBreakpointNameAdd () {} + + Options * + GetOptions () + { + return &m_option_group; + } + +protected: + virtual bool + DoExecute (Args& command, CommandReturnObject &result) + { + if (!m_name_options.m_name.OptionWasSet()) + { + result.SetError("No name option provided."); + return false; + } + + Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); + + if (target == NULL) + { + result.AppendError ("Invalid target. No existing target or breakpoints."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + Mutex::Locker locker; + target->GetBreakpointList().GetListMutex(locker); + + const BreakpointList &breakpoints = target->GetBreakpointList(); + + size_t num_breakpoints = breakpoints.GetSize(); + if (num_breakpoints == 0) + { + result.SetError("No breakpoints, cannot add names."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + // Particular breakpoint selected; disable that breakpoint. + BreakpointIDList valid_bp_ids; + CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); + + if (result.Succeeded()) + { + if (valid_bp_ids.GetSize() == 0) + { + result.SetError("No breakpoints specified, cannot add names."); + result.SetStatus (eReturnStatusFailed); + return false; + } + size_t num_valid_ids = valid_bp_ids.GetSize(); + for (size_t index = 0; index < num_valid_ids; index++) + { + lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); + BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); + Error error; // We don't need to check the error here, since the option parser checked it... + bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error); + } + } + + return true; + } + +private: + BreakpointNameOptionGroup m_name_options; + OptionGroupOptions m_option_group; +}; + + + +class CommandObjectBreakpointNameDelete : public CommandObjectParsed +{ +public: + CommandObjectBreakpointNameDelete (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "delete", + "Delete a name from the breakpoints provided.", + "breakpoint name delete "), + m_name_options(), + m_option_group(interpreter) + { + // Create the first variant for the first (and only) argument for this command. + CommandArgumentEntry arg1; + CommandArgumentData id_arg; + id_arg.arg_type = eArgTypeBreakpointID; + id_arg.arg_repetition = eArgRepeatOptional; + arg1.push_back(id_arg); + m_arguments.push_back (arg1); + + m_option_group.Append (&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); + m_option_group.Finalize(); + } + + virtual + ~CommandObjectBreakpointNameDelete () {} + + Options * + GetOptions () + { + return &m_option_group; + } + +protected: + virtual bool + DoExecute (Args& command, CommandReturnObject &result) + { + if (!m_name_options.m_name.OptionWasSet()) + { + result.SetError("No name option provided."); + return false; + } + + Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); + + if (target == NULL) + { + result.AppendError ("Invalid target. No existing target or breakpoints."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + Mutex::Locker locker; + target->GetBreakpointList().GetListMutex(locker); + + const BreakpointList &breakpoints = target->GetBreakpointList(); + + size_t num_breakpoints = breakpoints.GetSize(); + if (num_breakpoints == 0) + { + result.SetError("No breakpoints, cannot delete names."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + // Particular breakpoint selected; disable that breakpoint. + BreakpointIDList valid_bp_ids; + CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); + + if (result.Succeeded()) + { + if (valid_bp_ids.GetSize() == 0) + { + result.SetError("No breakpoints specified, cannot delete names."); + result.SetStatus (eReturnStatusFailed); + return false; + } + size_t num_valid_ids = valid_bp_ids.GetSize(); + for (size_t index = 0; index < num_valid_ids; index++) + { + lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); + BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); + bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue()); + } + } + + return true; + } + +private: + BreakpointNameOptionGroup m_name_options; + OptionGroupOptions m_option_group; +}; + +class CommandObjectBreakpointNameList : public CommandObjectParsed +{ +public: + CommandObjectBreakpointNameList (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "list", + "List either the names for a breakpoint or the breakpoints for a given name.", + "breakpoint name list "), + m_name_options(), + m_option_group(interpreter) + { + m_option_group.Append (&m_name_options); + m_option_group.Finalize(); + } + + virtual + ~CommandObjectBreakpointNameList () {} + + Options * + GetOptions () + { + return &m_option_group; + } + +protected: +protected: + virtual bool + DoExecute (Args& command, CommandReturnObject &result) + { + Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); + + if (target == NULL) + { + result.AppendError ("Invalid target. No existing target or breakpoints."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + if (m_name_options.m_name.OptionWasSet()) + { + const char *name = m_name_options.m_name.GetCurrentValue(); + Mutex::Locker locker; + target->GetBreakpointList().GetListMutex(locker); + + BreakpointList &breakpoints = target->GetBreakpointList(); + for (BreakpointSP bp_sp : breakpoints.Breakpoints()) + { + if (bp_sp->MatchesName(name)) + { + StreamString s; + bp_sp->GetDescription(&s, eDescriptionLevelBrief); + s.EOL(); + result.AppendMessage(s.GetData()); + } + } + + } + else if (m_name_options.m_breakpoint.OptionWasSet()) + { + BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID(m_name_options.m_breakpoint.GetCurrentValue()); + if (bp_sp) + { + std::vector names; + bp_sp->GetNames (names); + result.AppendMessage ("Names:"); + for (auto name : names) + result.AppendMessageWithFormat (" %s\n", name.c_str()); + } + else + { + result.AppendErrorWithFormat ("Could not find breakpoint %" PRId64 ".\n", + m_name_options.m_breakpoint.GetCurrentValue()); + result.SetStatus (eReturnStatusFailed); + return false; + } + } + else + { + result.SetError ("Must specify -N or -B option to list."); + result.SetStatus (eReturnStatusFailed); + return false; + } + return true; + } + +private: + BreakpointNameOptionGroup m_name_options; + OptionGroupOptions m_option_group; +}; + +//------------------------------------------------------------------------- +// CommandObjectMultiwordBreakpoint +//------------------------------------------------------------------------- +class CommandObjectBreakpointName : public CommandObjectMultiword +{ +public: + CommandObjectBreakpointName (CommandInterpreter &interpreter) : + CommandObjectMultiword(interpreter, + "name", + "A set of commands to manage name tags for breakpoints", + "breakpoint name []") + { + CommandObjectSP add_command_object (new CommandObjectBreakpointNameAdd (interpreter)); + CommandObjectSP delete_command_object (new CommandObjectBreakpointNameDelete (interpreter)); + CommandObjectSP list_command_object (new CommandObjectBreakpointNameList (interpreter)); + + LoadSubCommand ("add", add_command_object); + LoadSubCommand ("delete", delete_command_object); + LoadSubCommand ("list", list_command_object); + + } + + virtual + ~CommandObjectBreakpointName () + { + } + +}; + //------------------------------------------------------------------------- // CommandObjectMultiwordBreakpoint @@ -1769,6 +2300,7 @@ CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInter CommandObjectSP set_command_object (new CommandObjectBreakpointSet (interpreter)); CommandObjectSP command_command_object (new CommandObjectBreakpointCommand (interpreter)); CommandObjectSP modify_command_object (new CommandObjectBreakpointModify(interpreter)); + CommandObjectSP name_command_object (new CommandObjectBreakpointName(interpreter)); list_command_object->SetCommandName ("breakpoint list"); enable_command_object->SetCommandName("breakpoint enable"); @@ -1778,6 +2310,7 @@ CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInter set_command_object->SetCommandName("breakpoint set"); command_command_object->SetCommandName ("breakpoint command"); modify_command_object->SetCommandName ("breakpoint modify"); + name_command_object->SetCommandName ("breakpoint name"); LoadSubCommand ("list", list_command_object); LoadSubCommand ("enable", enable_command_object); @@ -1787,6 +2320,7 @@ CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInter LoadSubCommand ("set", set_command_object); LoadSubCommand ("command", command_command_object); LoadSubCommand ("modify", modify_command_object); + LoadSubCommand ("name", name_command_object); } CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint () @@ -1794,13 +2328,17 @@ CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint () } void -CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result, - BreakpointIDList *valid_ids) +CommandObjectMultiwordBreakpoint::VerifyIDs (Args &args, + Target *target, + bool allow_locations, + CommandReturnObject &result, + BreakpointIDList *valid_ids) { // args can be strings representing 1). integers (for breakpoint ids) // 2). the full breakpoint & location canonical representation // 3). the word "to" or a hyphen, representing a range (in which case there // had *better* be an entry both before & after of one of the first two types. + // 4). A breakpoint name // If args is empty, we will use the last created breakpoint (if there is one.) Args temp_args; @@ -1824,7 +2362,7 @@ CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (Args &args, Target *targe // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead generate a list of strings for // all the breakpoint ids in the range, and shove all of those breakpoint id strings into TEMP_ARGS. - BreakpointIDList::FindAndReplaceIDRanges (args, target, result, temp_args); + BreakpointIDList::FindAndReplaceIDRanges (args, target, allow_locations, result, temp_args); // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual BreakpointIDList: diff --git a/source/Commands/CommandObjectBreakpoint.h b/source/Commands/CommandObjectBreakpoint.h index 2d674b22d704..3fdd2a5f56be 100644 --- a/source/Commands/CommandObjectBreakpoint.h +++ b/source/Commands/CommandObjectBreakpoint.h @@ -38,8 +38,20 @@ public: ~CommandObjectMultiwordBreakpoint (); static void - VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids); + VerifyBreakpointOrLocationIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids) + { + VerifyIDs (args, target, true, result, valid_ids); + } + static void + VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids) + { + VerifyIDs (args, target, false, result, valid_ids); + } + +private: + static void + VerifyIDs (Args &args, Target *target, bool allow_locations, CommandReturnObject &result, BreakpointIDList *valid_ids); }; } // namespace lldb_private diff --git a/source/Commands/CommandObjectBreakpointCommand.cpp b/source/Commands/CommandObjectBreakpointCommand.cpp index fdb87d11900b..8f8404b712a5 100644 --- a/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/source/Commands/CommandObjectBreakpointCommand.cpp @@ -307,17 +307,16 @@ one command per line.\n" ); result.SetImmediateOutputStream (output_stream); result.SetImmediateErrorStream (error_stream); - bool stop_on_continue = true; - bool echo_commands = false; - bool print_results = true; - - debugger.GetCommandInterpreter().HandleCommands (commands, + CommandInterpreterRunOptions options; + options.SetStopOnContinue(true); + options.SetStopOnError (data->stop_on_error); + options.SetEchoCommands (true); + options.SetPrintResults (true); + options.SetAddToHistory (false); + + debugger.GetCommandInterpreter().HandleCommands (commands, &exe_ctx, - stop_on_continue, - data->stop_on_error, - echo_commands, - print_results, - eLazyBoolNo, + options, result); result.GetImmediateOutputStream()->Flush(); result.GetImmediateErrorStream()->Flush(); @@ -390,6 +389,10 @@ one command per line.\n" ); } break; + case 'D': + m_use_dummy = true; + break; + default: break; } @@ -406,6 +409,7 @@ one command per line.\n" ); m_stop_on_error = true; m_one_liner.clear(); m_function_name.clear(); + m_use_dummy = false; } const OptionDefinition* @@ -429,13 +433,14 @@ one command per line.\n" ); std::string m_one_liner; bool m_stop_on_error; std::string m_function_name; + bool m_use_dummy; }; protected: virtual bool DoExecute (Args& command, CommandReturnObject &result) { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); if (target == NULL) { @@ -462,7 +467,7 @@ protected: } BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); m_bp_options_vec.clear(); @@ -581,6 +586,9 @@ CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] = { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction, "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."}, + { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, + "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, + { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; @@ -595,7 +603,8 @@ public: CommandObjectParsed (interpreter, "delete", "Delete the set of commands from a breakpoint.", - NULL) + NULL), + m_options (interpreter) { CommandArgumentEntry arg; CommandArgumentData bp_id_arg; @@ -615,11 +624,70 @@ public: virtual ~CommandObjectBreakpointCommandDelete () {} + virtual Options * + GetOptions () + { + return &m_options; + } + + class CommandOptions : public Options + { + public: + + CommandOptions (CommandInterpreter &interpreter) : + Options (interpreter), + m_use_dummy (false) + { + } + + virtual + ~CommandOptions () {} + + virtual Error + SetOptionValue (uint32_t option_idx, const char *option_arg) + { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) + { + case 'D': + m_use_dummy = true; + break; + + default: + error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); + break; + } + + return error; + } + + void + OptionParsingStarting () + { + m_use_dummy = false; + } + + const OptionDefinition* + GetDefinitions () + { + return g_option_table; + } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + bool m_use_dummy; + }; + protected: virtual bool DoExecute (Args& command, CommandReturnObject &result) { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); if (target == NULL) { @@ -646,7 +714,7 @@ protected: } BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); if (result.Succeeded()) { @@ -680,8 +748,20 @@ protected: } return result.Succeeded(); } +private: + CommandOptions m_options; +}; + +OptionDefinition +CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, + "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, + + { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; + //------------------------------------------------------------------------- // CommandObjectBreakpointCommandList //------------------------------------------------------------------------- @@ -744,7 +824,7 @@ protected: } BreakpointIDList valid_bp_ids; - CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); + CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); if (result.Succeeded()) { diff --git a/source/Commands/CommandObjectCommands.cpp b/source/Commands/CommandObjectCommands.cpp index 7d9bb7dad8fd..f98eac055f24 100644 --- a/source/Commands/CommandObjectCommands.cpp +++ b/source/Commands/CommandObjectCommands.cpp @@ -366,7 +366,7 @@ protected: // Instance variables to hold the values for command options. OptionValueBoolean m_stop_on_error; - OptionValueBoolean m_silent_run; + OptionValueBoolean m_silent_run; OptionValueBoolean m_stop_on_continue; }; @@ -387,14 +387,15 @@ protected: m_options.m_stop_on_continue.OptionWasSet()) { // Use user set settings - LazyBool print_command = m_options.m_silent_run.GetCurrentValue() ? eLazyBoolNo : eLazyBoolYes; + CommandInterpreterRunOptions options; + options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue()); + options.SetStopOnError (m_options.m_stop_on_error.GetCurrentValue()); + options.SetEchoCommands (!m_options.m_silent_run.GetCurrentValue()); + options.SetPrintResults (!m_options.m_silent_run.GetCurrentValue()); + m_interpreter.HandleCommandsFromFile (cmd_file, exe_ctx, - m_options.m_stop_on_continue.GetCurrentValue() ? eLazyBoolYes : eLazyBoolNo, // Stop on continue - m_options.m_stop_on_error.GetCurrentValue() ? eLazyBoolYes : eLazyBoolNo, // Stop on error - print_command, // Echo command - print_command, // Print command output - eLazyBoolCalculate, // Add to history + options, result); } @@ -402,13 +403,10 @@ protected: { // 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, - eLazyBoolCalculate, // Stop on continue - eLazyBoolCalculate, // Stop on error - eLazyBoolCalculate, // Echo command - eLazyBoolCalculate, // Print command output - eLazyBoolCalculate, // Add to history + options, result); } @@ -830,8 +828,16 @@ protected: { if (m_interpreter.CommandExists (command_name)) { - result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", - command_name); + if (cmd_obj->IsRemovable()) + { + result.AppendErrorWithFormat ("'%s' is not an alias, it is a debugger command which can be removed using the 'command delete' command.\n", + command_name); + } + else + { + result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", + command_name); + } result.SetStatus (eReturnStatusFailed); } else @@ -868,6 +874,77 @@ protected: } }; +#pragma mark CommandObjectCommandsDelete +//------------------------------------------------------------------------- +// CommandObjectCommandsDelete +//------------------------------------------------------------------------- + +class CommandObjectCommandsDelete : public CommandObjectParsed +{ +public: + CommandObjectCommandsDelete (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "command delete", + "Allow the user to delete user-defined regular expression, python or multi-word commands.", + NULL) + { + CommandArgumentEntry arg; + CommandArgumentData alias_arg; + + // Define the first (and only) variant of this arg. + alias_arg.arg_type = eArgTypeCommandName; + alias_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the argument entry. + arg.push_back (alias_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back (arg); + } + + ~CommandObjectCommandsDelete() + { + } + +protected: + bool + DoExecute (Args& args, CommandReturnObject &result) + { + CommandObject::CommandMap::iterator pos; + + if (args.GetArgumentCount() != 0) + { + const char *command_name = args.GetArgumentAtIndex(0); + if (m_interpreter.CommandExists (command_name)) + { + if (m_interpreter.RemoveCommand (command_name)) + { + result.SetStatus (eReturnStatusSuccessFinishNoResult); + } + else + { + result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", + command_name); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n", + command_name); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + result.AppendErrorWithFormat ("must call '%s' with one or more valid user defined regular expression, python or multi-word command names", GetCommandName ()); + result.SetStatus (eReturnStatusFailed); + } + + return result.Succeeded(); + } +}; + //------------------------------------------------------------------------- // CommandObjectCommandsAddRegex //------------------------------------------------------------------------- @@ -875,7 +952,7 @@ protected: class CommandObjectCommandsAddRegex : public CommandObjectParsed, - public IOHandlerDelegate + public IOHandlerDelegateMultiline { public: CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) : @@ -883,7 +960,7 @@ public: "command regex", "Allow the user to create a regular expression command.", "command regex [s/// ...]"), - IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand), + IOHandlerDelegateMultiline ("", IOHandlerDelegate::Completion::LLDBCommand), m_options (interpreter) { SetHelpLong( @@ -920,8 +997,8 @@ public: protected: - virtual void - IOHandlerActivated (IOHandler &io_handler) + void + IOHandlerActivated (IOHandler &io_handler) override { StreamFileSP output_sp(io_handler.GetOutputStreamFile()); if (output_sp) @@ -931,8 +1008,8 @@ protected: } } - virtual void - IOHandlerInputComplete (IOHandler &io_handler, std::string &data) + void + IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override { io_handler.SetIsDone(true); if (m_regex_cmd_ap.get()) @@ -944,7 +1021,6 @@ protected: bool check_only = false; for (size_t i=0; i ", // Prompt and clear line + "> ", // Prompt + NULL, // Continuation prompt multiple_lines, + color_prompt, 0, // Don't show line numbers *this)); @@ -1110,21 +1147,25 @@ protected: if (second_separator_char_pos == std::string::npos) { - error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s'", + error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s' in '%.*s'", separator_char, (int)(regex_sed.size() - first_separator_char_pos - 1), - regex_sed.data() + (first_separator_char_pos + 1)); - return error; + regex_sed.data() + (first_separator_char_pos + 1), + (int)regex_sed.size(), + regex_sed.data()); + return error; } const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1); if (third_separator_char_pos == std::string::npos) { - error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s'", + error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s' in '%.*s'", separator_char, (int)(regex_sed.size() - second_separator_char_pos - 1), - regex_sed.data() + (second_separator_char_pos + 1)); + regex_sed.data() + (second_separator_char_pos + 1), + (int)regex_sed.size(), + regex_sed.data()); return error; } @@ -1262,8 +1303,8 @@ private: std::string m_syntax; }; - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -1292,15 +1333,24 @@ public: CommandObjectPythonFunction (CommandInterpreter &interpreter, std::string name, std::string funct, + std::string help, ScriptedCommandSynchronicity synch) : CommandObjectRaw (interpreter, name.c_str(), - (std::string("Run Python function ") + funct).c_str(), + NULL, NULL), m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) { + if (!help.empty()) + SetHelp(help.c_str()); + else + { + StreamString stream; + stream.Printf("For more information run 'help %s'",name.c_str()); + SetHelp(stream.GetData()); + } } virtual @@ -1357,7 +1407,8 @@ protected: raw_command_line, m_synchro, result, - error) == false) + error, + m_exe_ctx) == false) { result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); @@ -1617,7 +1668,12 @@ protected: switch (short_option) { case 'f': - m_funct_name = std::string(option_arg); + if (option_arg) + m_funct_name.assign(option_arg); + break; + case 'h': + if (option_arg) + m_short_help.assign(option_arg); break; case 's': m_synchronicity = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); @@ -1635,7 +1691,8 @@ protected: void OptionParsingStarting () { - m_funct_name = ""; + m_funct_name.clear(); + m_short_help.clear(); m_synchronicity = eScriptedCommandSynchronicitySynchronous; } @@ -1652,6 +1709,7 @@ protected: // Instance variables to hold the values for command options. std::string m_funct_name; + std::string m_short_help; ScriptedCommandSynchronicity m_synchronicity; }; @@ -1695,6 +1753,7 @@ protected: CommandObjectSP command_obj_sp(new CommandObjectPythonFunction (m_interpreter, m_cmd_name, funct_name_str.c_str(), + m_short_help, m_synchronicity)); if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true)) @@ -1748,8 +1807,9 @@ protected: return false; } - // Store the command name and synchronicity in case we get multi-line input + // Store the options in case we get multi-line input m_cmd_name = command.GetArgumentAtIndex(0); + m_short_help.assign(m_options.m_short_help); m_synchronicity = m_options.m_synchronicity; if (m_options.m_funct_name.empty()) @@ -1764,6 +1824,7 @@ protected: CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, m_cmd_name, m_options.m_funct_name, + m_options.m_short_help, m_synchronicity)); if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { @@ -1782,6 +1843,7 @@ protected: CommandOptions m_options; std::string m_cmd_name; + std::string m_short_help; ScriptedCommandSynchronicity m_synchronicity; }; @@ -1797,6 +1859,7 @@ OptionDefinition CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] = { { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."}, + { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeHelpText, "The help text to display for this command."}, { LLDB_OPT_SET_1, false, "synchronicity", 's', OptionParser::eRequiredArgument, NULL, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."}, { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; @@ -1949,11 +2012,11 @@ public: "A set of commands for managing or customizing script commands.", "command script []") { - LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter))); - LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter))); - LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter))); + LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter))); + LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter))); + LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter))); LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter))); - LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter))); + LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter))); } ~CommandObjectMultiwordCommandsScript () @@ -1978,9 +2041,10 @@ CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpret LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter))); LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter))); LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter))); + LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsDelete (interpreter))); LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter))); - LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter))); - LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter))); + LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter))); + LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter))); } CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands () diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp index 079c62ddfdff..b4c559c81cc5 100644 --- a/source/Commands/CommandObjectExpression.cpp +++ b/source/Commands/CommandObjectExpression.cpp @@ -281,7 +281,7 @@ CommandObjectExpression::EvaluateExpression Target *target = exe_ctx.GetTargetPtr(); if (!target) - target = Host::GetDummyTarget(m_interpreter.GetDebugger()).get(); + target = GetDummyTarget(); if (target) { @@ -425,11 +425,15 @@ CommandObjectExpression::GetMultilineExpression () m_expr_line_count = 0; Debugger &debugger = GetCommandInterpreter().GetDebugger(); + bool color_prompt = debugger.GetUseColor(); const bool multiple_lines = true; // Get multiple lines IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, + IOHandler::Type::Expression, "lldb-expr", // Name of input reader for history NULL, // No prompt + NULL, // Continuation prompt multiple_lines, + color_prompt, 1, // Show line numbers starting at 1 *this)); diff --git a/source/Commands/CommandObjectMemory.cpp b/source/Commands/CommandObjectMemory.cpp index bfbb296158a9..6c06ec831830 100644 --- a/source/Commands/CommandObjectMemory.cpp +++ b/source/Commands/CommandObjectMemory.cpp @@ -33,8 +33,10 @@ #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" #include "lldb/Interpreter/OptionValueString.h" #include "lldb/Symbol/TypeList.h" +#include "lldb/Target/MemoryHistory.h" #include "lldb/Target/Process.h" #include "lldb/Target/StackFrame.h" +#include "lldb/Target/Thread.h" using namespace lldb; using namespace lldb_private; @@ -612,7 +614,16 @@ protected: } size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); - size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); + + // TODO For non-8-bit byte addressable architectures this needs to be + // revisited to fully support all lldb's range of formatting options. + // Furthermore code memory reads (for those architectures) will not + // be correctly formatted even w/o formatting options. + size_t item_byte_size = + target->GetArchitecture().GetDataByteSize() > 1 ? + target->GetArchitecture().GetDataByteSize() : + m_format_options.GetByteSizeValue().GetCurrentValue(); + const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue(); if (total_byte_size == 0) @@ -659,7 +670,7 @@ protected: total_byte_size = end_addr - addr; item_count = total_byte_size / item_byte_size; } - + uint32_t max_unforced_size = target->GetMaximumMemReadSize(); if (total_byte_size > max_unforced_size && !m_memory_options.m_force) @@ -856,7 +867,8 @@ protected: result.SetStatus(eReturnStatusSuccessFinishResult); DataExtractor data (data_sp, target->GetArchitecture().GetByteOrder(), - target->GetArchitecture().GetAddressByteSize()); + target->GetArchitecture().GetAddressByteSize(), + target->GetArchitecture().GetDataByteSize()); Format format = m_format_options.GetFormat(); if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) ) @@ -890,7 +902,7 @@ protected: format, item_byte_size, item_count, - num_per_line, + num_per_line / target->GetArchitecture().GetDataByteSize(), addr, 0, 0, @@ -1078,7 +1090,7 @@ protected: lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error); if (high_addr == LLDB_INVALID_ADDRESS || error.Fail()) { - result.AppendError("invalid low address"); + result.AppendError("invalid high address"); return false; } @@ -1667,6 +1679,96 @@ protected: OptionGroupWriteMemory m_memory_options; }; +//---------------------------------------------------------------------- +// Get malloc/free history of a memory address. +//---------------------------------------------------------------------- +class CommandObjectMemoryHistory : public CommandObjectParsed +{ +public: + + CommandObjectMemoryHistory (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "memory history", + "Prints out the recorded stack traces for allocation/deallocation of a memory address.", + NULL, + eFlagRequiresTarget | eFlagRequiresProcess | eFlagProcessMustBePaused | eFlagProcessMustBeLaunched) + { + CommandArgumentEntry arg1; + CommandArgumentData addr_arg; + + // Define the first (and only) variant of this arg. + addr_arg.arg_type = eArgTypeAddress; + addr_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the argument entry. + arg1.push_back (addr_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back (arg1); + } + + virtual + ~CommandObjectMemoryHistory () + { + } + + virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) + { + return m_cmd_name.c_str(); + } + +protected: + virtual bool + DoExecute (Args& command, CommandReturnObject &result) + { + const size_t argc = command.GetArgumentCount(); + + if (argc == 0 || argc > 1) + { + result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + Error error; + lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx, + command.GetArgumentAtIndex(0), + LLDB_INVALID_ADDRESS, + &error); + + if (addr == LLDB_INVALID_ADDRESS) + { + result.AppendError("invalid address expression"); + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + Stream *output_stream = &result.GetOutputStream(); + + const ProcessSP &process_sp = m_exe_ctx.GetProcessSP(); + const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp); + + if (! memory_history.get()) + { + result.AppendError("no available memory history provider"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + HistoryThreads thread_list = memory_history->GetHistoryThreads(addr); + + for (auto thread : thread_list) { + thread->GetStatus(*output_stream, 0, UINT32_MAX, 0); + } + + result.SetStatus(eReturnStatusSuccessFinishResult); + + return true; + } + +}; + //------------------------------------------------------------------------- // CommandObjectMemory @@ -1681,6 +1783,7 @@ CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) : LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter))); LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter))); LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter))); + LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter))); } CommandObjectMemory::~CommandObjectMemory () diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp index 9998dbdccdad..d176d52cb487 100644 --- a/source/Commands/CommandObjectPlatform.cpp +++ b/source/Commands/CommandObjectPlatform.cpp @@ -302,7 +302,7 @@ protected: Stream &ostrm = result.GetOutputStream(); ostrm.Printf("Available platforms:\n"); - PlatformSP host_platform_sp (Platform::GetDefaultPlatform()); + PlatformSP host_platform_sp (Platform::GetHostPlatform()); ostrm.Printf ("%s: %s\n", host_platform_sp->GetPluginName().GetCString(), host_platform_sp->GetDescription()); @@ -1347,7 +1347,6 @@ protected: ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info, debugger, target, - debugger.GetListener(), error)); if (process_sp && process_sp->IsAlive()) { @@ -1933,7 +1932,7 @@ public: { Error err; ProcessSP remote_process_sp = - platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), NULL, m_interpreter.GetDebugger().GetListener(), err); + platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), NULL, err); if (err.Fail()) { result.AppendError(err.AsCString()); diff --git a/source/Commands/CommandObjectProcess.cpp b/source/Commands/CommandObjectProcess.cpp index 6536c6ef1693..ec7b478fbecc 100644 --- a/source/Commands/CommandObjectProcess.cpp +++ b/source/Commands/CommandObjectProcess.cpp @@ -258,8 +258,9 @@ protected: // Save the arguments for subsequent runs in the current target. target->SetRunArguments (launch_args); } - - Error error = target->Launch(debugger.GetListener(), m_options.launch_info); + + StreamString stream; + Error error = target->Launch(m_options.launch_info, &stream); if (error.Success()) { @@ -267,6 +268,9 @@ protected: ProcessSP process_sp (target->GetProcessSP()); if (process_sp) { + const char *data = stream.GetData(); + if (data && strlen(data) > 0) + result.AppendMessage(stream.GetData()); result.AppendMessageWithFormat ("Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), exe_module_sp->GetFileSpec().GetPath().c_str(), archname); result.SetStatus (eReturnStatusSuccessFinishResult); result.SetDidChangeProcessState (true); @@ -564,15 +568,18 @@ protected: if (error.Success()) { result.SetStatus (eReturnStatusSuccessContinuingNoResult); - StateType state = process->WaitForProcessToStop (NULL, NULL, false, listener_sp.get()); + StreamString stream; + StateType state = process->WaitForProcessToStop (NULL, NULL, false, listener_sp.get(), &stream); process->RestoreProcessEvents(); result.SetDidChangeProcessState (true); + if (stream.GetData()) + result.AppendMessage(stream.GetData()); + if (state == eStateStopped) { - result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else @@ -791,7 +798,12 @@ protected: } } - Error error(process->Resume()); + StreamString stream; + Error error; + if (synchronous_execution) + error = process->ResumeSynchronous (&stream); + else + error = process->Resume (); if (error.Success()) { @@ -803,10 +815,11 @@ protected: result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); if (synchronous_execution) { - state = process->WaitForProcessToStop (NULL); + // If any state changed events had anything to say, add that to the result + if (stream.GetData()) + result.AppendMessage(stream.GetData()); result.SetDidChangeProcessState (true); - result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else diff --git a/source/Commands/CommandObjectSource.cpp b/source/Commands/CommandObjectSource.cpp index 6b1b6aacc857..8fb03e69ac42 100644 --- a/source/Commands/CommandObjectSource.cpp +++ b/source/Commands/CommandObjectSource.cpp @@ -421,7 +421,7 @@ protected: { const bool show_inlines = true; m_breakpoint_locations.Reset (start_file, 0, show_inlines); - SearchFilter target_search_filter (m_exe_ctx.GetTargetSP()); + SearchFilterForUnconstrainedSearches target_search_filter (m_exe_ctx.GetTargetSP()); target_search_filter.Search (m_breakpoint_locations); } @@ -682,19 +682,21 @@ protected: m_breakpoint_locations.Clear(); const bool show_inlines = true; m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines); - SearchFilter target_search_filter (target->shared_from_this()); + SearchFilterForUnconstrainedSearches target_search_filter (target->shared_from_this()); target_search_filter.Search (m_breakpoint_locations); } bool show_fullpaths = true; bool show_module = true; bool show_inlined_frames = true; + const bool show_function_arguments = true; sc.DumpStopContext(&result.GetOutputStream(), m_exe_ctx.GetBestExecutionContextScope(), sc.line_entry.range.GetBaseAddress(), show_fullpaths, show_module, - show_inlined_frames); + show_inlined_frames, + show_function_arguments); result.GetOutputStream().EOL(); if (m_options.num_lines == 0) @@ -741,7 +743,7 @@ protected: { const bool show_inlines = true; m_breakpoint_locations.Reset (last_file_sp->GetFileSpec(), 0, show_inlines); - SearchFilter target_search_filter (target->shared_from_this()); + SearchFilterForUnconstrainedSearches target_search_filter (target->shared_from_this()); target_search_filter.Search (m_breakpoint_locations); } } @@ -844,7 +846,7 @@ protected: { const bool show_inlines = true; m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines); - SearchFilter target_search_filter (target->shared_from_this()); + SearchFilterForUnconstrainedSearches target_search_filter (target->shared_from_this()); target_search_filter.Search (m_breakpoint_locations); } else diff --git a/source/Commands/CommandObjectSyntax.cpp b/source/Commands/CommandObjectSyntax.cpp index d2021ea3eb19..5093c3b99339 100644 --- a/source/Commands/CommandObjectSyntax.cpp +++ b/source/Commands/CommandObjectSyntax.cpp @@ -69,12 +69,18 @@ CommandObjectSyntax::DoExecute (Args& command, CommandReturnObject &result) { std::string sub_command = command.GetArgumentAtIndex (i); if (!cmd_obj->IsMultiwordObject()) + { all_okay = false; + break; + } else { cmd_obj = cmd_obj->GetSubcommandObject(sub_command.c_str()); if (!cmd_obj) + { all_okay = false; + break; + } } } diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp index 024f7b5a0415..0d9ffda1e96b 100644 --- a/source/Commands/CommandObjectTarget.cpp +++ b/source/Commands/CommandObjectTarget.cpp @@ -39,6 +39,7 @@ #include "lldb/Interpreter/OptionGroupPlatform.h" #include "lldb/Interpreter/OptionGroupUInt64.h" #include "lldb/Interpreter/OptionGroupUUID.h" +#include "lldb/Interpreter/OptionGroupString.h" #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/FuncUnwinders.h" @@ -2844,7 +2845,7 @@ public: "Set the load addresses for one or more sections in a target module.", "target modules load [--file --uuid ]
[
....]"), m_option_group (interpreter), - m_file_option (LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeFilename, "Fullpath or basename for module to load."), + m_file_option (LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName, "Fullpath or basename for module to load.", ""), m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset, "Set the load address for all sections to be the virtual address in the file plus the offset.", 0) { m_option_group.Append (&m_uuid_option_group, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); @@ -2884,7 +2885,26 @@ protected: if (m_file_option.GetOptionValue().OptionWasSet()) { search_using_module_spec = true; - module_spec.GetFileSpec() = m_file_option.GetOptionValue().GetCurrentValue(); + const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue(); + const bool use_global_module_list = true; + ModuleList module_list; + const size_t num_matches = FindModulesByName (target, arg_cstr, module_list, use_global_module_list); + if (num_matches == 1) + { + module_spec.GetFileSpec() = module_list.GetModuleAtIndex(0)->GetFileSpec(); + } + else if (num_matches > 1 ) + { + 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); + } } if (m_uuid_option_group.GetOptionValue().OptionWasSet()) @@ -3070,7 +3090,7 @@ protected: OptionGroupOptions m_option_group; OptionGroupUUID m_uuid_option_group; - OptionGroupFile m_file_option; + OptionGroupString m_file_option; OptionGroupUInt64 m_slide_option; }; @@ -3724,45 +3744,85 @@ protected: if (func_unwinders_sp.get() == NULL) continue; - Address first_non_prologue_insn (func_unwinders_sp->GetFirstNonPrologueInsn(*target)); - if (first_non_prologue_insn.IsValid()) - { - result.GetOutputStream().Printf("First non-prologue instruction is at address 0x%" PRIx64 " or offset %" PRId64 " into the function.\n", first_non_prologue_insn.GetLoadAddress(target), first_non_prologue_insn.GetLoadAddress(target) - start_addr); - result.GetOutputStream().Printf ("\n"); - } + result.GetOutputStream().Printf("UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr); UnwindPlanSP non_callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread.get(), -1); if (non_callsite_unwind_plan.get()) { - result.GetOutputStream().Printf("Asynchronous (not restricted to call-sites) UnwindPlan for %s`%s (start addr 0x%" PRIx64 "):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr); - non_callsite_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); - result.GetOutputStream().Printf ("\n"); + result.GetOutputStream().Printf("Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n", non_callsite_unwind_plan->GetSourceName().AsCString()); } - - UnwindPlanSP callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(-1); + UnwindPlanSP callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(*target, -1); if (callsite_unwind_plan.get()) { - result.GetOutputStream().Printf("Synchronous (restricted to call-sites) UnwindPlan for %s`%s (start addr 0x%" PRIx64 "):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr); - callsite_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); - result.GetOutputStream().Printf ("\n"); + result.GetOutputStream().Printf("Synchronous (restricted to call-sites) UnwindPlan is '%s'\n", callsite_unwind_plan->GetSourceName().AsCString()); + } + UnwindPlanSP fast_unwind_plan = func_unwinders_sp->GetUnwindPlanFastUnwind(*thread.get()); + if (fast_unwind_plan.get()) + { + result.GetOutputStream().Printf("Fast UnwindPlan is '%s'\n", fast_unwind_plan->GetSourceName().AsCString()); } - UnwindPlanSP arch_default_unwind_plan = func_unwinders_sp->GetUnwindPlanArchitectureDefault(*thread.get()); - if (arch_default_unwind_plan.get()) + result.GetOutputStream().Printf("\n"); + + UnwindPlanSP assembly_sp = func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread.get(), 0); + if (assembly_sp) { - result.GetOutputStream().Printf("Architecture default UnwindPlan for %s`%s (start addr 0x%" PRIx64 "):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr); - arch_default_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); - result.GetOutputStream().Printf ("\n"); + result.GetOutputStream().Printf("Assembly language inspection UnwindPlan:\n"); + assembly_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); } + - UnwindPlanSP fast_unwind_plan = func_unwinders_sp->GetUnwindPlanFastUnwind(*thread.get()); - if (fast_unwind_plan.get()) + UnwindPlanSP ehframe_sp = func_unwinders_sp->GetEHFrameUnwindPlan(*target, 0); + if (ehframe_sp) { - result.GetOutputStream().Printf("Fast UnwindPlan for %s`%s (start addr 0x%" PRIx64 "):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr); + result.GetOutputStream().Printf("eh_frame UnwindPlan:\n"); + ehframe_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + + UnwindPlanSP ehframe_augmented_sp = func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread.get(), 0); + if (ehframe_augmented_sp) + { + result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n"); + ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + + UnwindPlanSP compact_unwind_sp = func_unwinders_sp->GetCompactUnwindUnwindPlan(*target, 0); + if (compact_unwind_sp) + { + result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n"); + compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + + if (fast_unwind_plan) + { + result.GetOutputStream().Printf("Fast UnwindPlan:\n"); fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); - result.GetOutputStream().Printf ("\n"); + result.GetOutputStream().Printf("\n"); } + ABISP abi_sp = process->GetABI(); + if (abi_sp) + { + UnwindPlan arch_default(lldb::eRegisterKindGeneric); + if (abi_sp->CreateDefaultUnwindPlan (arch_default)) + { + result.GetOutputStream().Printf("Arch default UnwindPlan:\n"); + arch_default.Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + + UnwindPlan arch_entry(lldb::eRegisterKindGeneric); + if (abi_sp->CreateFunctionEntryUnwindPlan (arch_entry)) + { + result.GetOutputStream().Printf("Arch default at entry point UnwindPlan:\n"); + arch_entry.Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + } result.GetOutputStream().Printf ("\n"); } @@ -4999,7 +5059,7 @@ protected: { m_stop_hook_sp.reset(); - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + Target *target = GetSelectedOrDummyTarget(); if (target) { Target::StopHookSP new_hook_sp = target->CreateStopHook(); @@ -5151,7 +5211,7 @@ protected: bool DoExecute (Args& command, CommandReturnObject &result) { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + Target *target = GetSelectedOrDummyTarget(); if (target) { // FIXME: see if we can use the breakpoint id style parser? @@ -5227,7 +5287,7 @@ protected: bool DoExecute (Args& command, CommandReturnObject &result) { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + Target *target = GetSelectedOrDummyTarget(); if (target) { // FIXME: see if we can use the breakpoint id style parser? @@ -5297,7 +5357,7 @@ protected: bool DoExecute (Args& command, CommandReturnObject &result) { - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + Target *target = GetSelectedOrDummyTarget(); if (!target) { result.AppendError ("invalid target\n"); diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp index e7a8652ac898..bace4e58b4ad 100644 --- a/source/Commands/CommandObjectThread.cpp +++ b/source/Commands/CommandObjectThread.cpp @@ -46,7 +46,108 @@ using namespace lldb_private; // CommandObjectThreadBacktrace //------------------------------------------------------------------------- -class CommandObjectThreadBacktrace : public CommandObjectParsed +class CommandObjectIterateOverThreads : public CommandObjectParsed +{ +public: + CommandObjectIterateOverThreads (CommandInterpreter &interpreter, + const char *name, + const char *help, + const char *syntax, + uint32_t flags) : + CommandObjectParsed (interpreter, name, help, syntax, flags) + { + } + + virtual ~CommandObjectIterateOverThreads() {} + virtual bool + DoExecute (Args& command, CommandReturnObject &result) + { + result.SetStatus (m_success_return); + + if (command.GetArgumentCount() == 0) + { + Thread *thread = m_exe_ctx.GetThreadPtr(); + if (!HandleOneThread (*thread, result)) + return false; + } + else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0) + { + Process *process = m_exe_ctx.GetProcessPtr(); + uint32_t idx = 0; + for (ThreadSP thread_sp : process->Threads()) + { + if (idx != 0 && m_add_return) + result.AppendMessage(""); + + if (!HandleOneThread(*(thread_sp.get()), result)) + return false; + ++idx; + } + } + else + { + const size_t num_args = command.GetArgumentCount(); + Process *process = m_exe_ctx.GetProcessPtr(); + Mutex::Locker locker (process->GetThreadList().GetMutex()); + std::vector thread_sps; + + for (size_t i = 0; i < num_args; i++) + { + bool success; + + uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success); + if (!success) + { + result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); + result.SetStatus (eReturnStatusFailed); + return false; + } + + thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx)); + + if (!thread_sps[i]) + { + result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i)); + result.SetStatus (eReturnStatusFailed); + return false; + } + + } + + for (uint32_t i = 0; i < num_args; i++) + { + if (!HandleOneThread (*(thread_sps[i].get()), result)) + return false; + + if (i < num_args - 1 && m_add_return) + result.AppendMessage(""); + } + } + return result.Succeeded(); + } + +protected: + + // Override this to do whatever you need to do for one thread. + // + // If you return false, the iteration will stop, otherwise it will proceed. + // The result is set to m_success_return (defaults to eReturnStatusSuccessFinishResult) before the iteration, + // so you only need to set the return status in HandleOneThread if you want to indicate an error. + // If m_add_return is true, a blank line will be inserted between each of the listings (except the last one.) + + virtual bool + HandleOneThread (Thread &thread, CommandReturnObject &result) = 0; + + ReturnStatus m_success_return = eReturnStatusSuccessFinishResult; + bool m_add_return = true; + +}; + +//------------------------------------------------------------------------- +// CommandObjectThreadBacktrace +//------------------------------------------------------------------------- + +class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads { public: @@ -134,7 +235,7 @@ public: }; CommandObjectThreadBacktrace (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, + CommandObjectIterateOverThreads (interpreter, "thread backtrace", "Show the stack for one or more threads. If no threads are specified, show the currently selected thread. Use the thread-index \"all\" to see all threads.", NULL, @@ -145,18 +246,6 @@ public: eFlagProcessMustBePaused ), m_options(interpreter) { - CommandArgumentEntry arg; - CommandArgumentData thread_idx_arg; - - // Define the first (and only) variant of this arg. - thread_idx_arg.arg_type = eArgTypeThreadIndex; - thread_idx_arg.arg_repetition = eArgRepeatStar; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (thread_idx_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); } ~CommandObjectThreadBacktrace() @@ -197,106 +286,28 @@ protected: } virtual bool - DoExecute (Args& command, CommandReturnObject &result) - { - result.SetStatus (eReturnStatusSuccessFinishResult); + HandleOneThread (Thread &thread, CommandReturnObject &result) + { Stream &strm = result.GetOutputStream(); // Don't show source context when doing backtraces. const uint32_t num_frames_with_source = 0; - if (command.GetArgumentCount() == 0) - { - Thread *thread = m_exe_ctx.GetThreadPtr(); - // Thread::GetStatus() returns the number of frames shown. - if (thread->GetStatus (strm, + + if (!thread.GetStatus (strm, m_options.m_start, m_options.m_count, num_frames_with_source)) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - if (m_options.m_extended_backtrace) - { - DoExtendedBacktrace (thread, result); - } - } - } - else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0) { - Process *process = m_exe_ctx.GetProcessPtr(); - uint32_t idx = 0; - for (ThreadSP thread_sp : process->Threads()) - { - if (idx != 0) - result.AppendMessage(""); - - if (!thread_sp->GetStatus (strm, - m_options.m_start, - m_options.m_count, - num_frames_with_source)) - { - result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", idx); - result.SetStatus (eReturnStatusFailed); - return false; - } - if (m_options.m_extended_backtrace) - { - DoExtendedBacktrace (thread_sp.get(), result); - } - - ++idx; - } + result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", thread.GetIndexID()); + result.SetStatus (eReturnStatusFailed); + return false; } - else + if (m_options.m_extended_backtrace) { - const size_t num_args = command.GetArgumentCount(); - Process *process = m_exe_ctx.GetProcessPtr(); - Mutex::Locker locker (process->GetThreadList().GetMutex()); - std::vector thread_sps; - - for (size_t i = 0; i < num_args; i++) - { - bool success; - - uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success); - if (!success) - { - result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); - result.SetStatus (eReturnStatusFailed); - return false; - } - - thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx)); - - if (!thread_sps[i]) - { - result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i)); - result.SetStatus (eReturnStatusFailed); - return false; - } - - } - - for (uint32_t i = 0; i < num_args; i++) - { - if (!thread_sps[i]->GetStatus (strm, - m_options.m_start, - m_options.m_count, - num_frames_with_source)) - { - result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i)); - result.SetStatus (eReturnStatusFailed); - return false; - } - if (m_options.m_extended_backtrace) - { - DoExtendedBacktrace (thread_sps[i].get(), result); - } - - if (i < num_args - 1) - result.AppendMessage(""); - } + DoExtendedBacktrace (&thread, result); } - return result.Succeeded(); + + return true; } CommandOptions m_options; @@ -379,6 +390,12 @@ public: break; } break; + case 'C': + { + m_class_name.clear(); + m_class_name.assign(option_arg); + } + break; case 'm': { OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; @@ -416,6 +433,7 @@ public: m_run_mode = eOnlyDuringStepping; m_avoid_regexp.clear(); m_step_in_target.clear(); + m_class_name.clear(); m_step_count = 1; } @@ -435,7 +453,8 @@ public: RunMode m_run_mode; std::string m_avoid_regexp; std::string m_step_in_target; - int32_t m_step_count; + std::string m_class_name; + uint32_t m_step_count; }; CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter, @@ -520,6 +539,22 @@ protected: } } + if (m_step_type == eStepTypeScripted) + { + if (m_options.m_class_name.empty()) + { + result.AppendErrorWithFormat ("empty class name for scripted step."); + result.SetStatus(eReturnStatusFailed); + return false; + } + else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists(m_options.m_class_name.c_str())) + { + result.AppendErrorWithFormat ("class for scripted step: \"%s\" does not exist.", m_options.m_class_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + const bool abort_other_plans = false; const lldb::RunMode stop_other_threads = m_options.m_run_mode; @@ -530,7 +565,7 @@ protected: bool_stop_other_threads = false; else if (m_options.m_run_mode == eOnlyDuringStepping) { - if (m_step_type == eStepTypeOut) + if (m_step_type == eStepTypeOut || m_step_type == eStepTypeScripted) bool_stop_other_threads = false; else bool_stop_other_threads = true; @@ -599,6 +634,12 @@ protected: thread->GetSelectedFrameIndex(), m_options.m_step_out_avoid_no_debug); } + else if (m_step_type == eStepTypeScripted) + { + new_plan_sp = thread->QueueThreadPlanForStepScripted (abort_other_plans, + m_options.m_class_name.c_str(), + bool_stop_other_threads); + } else { result.AppendError ("step type is not supported"); @@ -622,8 +663,15 @@ protected: } } + process->GetThreadList().SetSelectedThreadByID (thread->GetID()); - process->Resume (); + + StreamString stream; + Error error; + if (synchronous_execution) + error = process->ResumeSynchronous (&stream); + else + error = process->Resume (); // There is a race condition where this thread will return up the call stack to the main command handler // and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has @@ -632,17 +680,12 @@ protected: if (synchronous_execution) { - StateType state = process->WaitForProcessToStop (NULL); - - //EventSP event_sp; - //StateType state = process->WaitForStateChangedEvents (NULL, event_sp); - //while (! StateIsStoppedState (state)) - // { - // state = process->WaitForStateChangedEvents (NULL, event_sp); - // } + // If any state changed events had anything to say, add that to the result + if (stream.GetData()) + result.AppendMessage(stream.GetData()); + process->GetThreadList().SetSelectedThreadByID (thread->GetID()); result.SetDidChangeProcessState (true); - result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else @@ -686,10 +729,11 @@ CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] = { { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether stepping into functions will step over functions with no debug information."}, { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug", 'A', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information."}, -{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."}, -{ LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, NULL, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."}, -{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in."}, -{ LLDB_OPT_SET_1, false, "step-in-target", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."}, +{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."}, +{ LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, NULL, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."}, +{ LLDB_OPT_SET_1, false, "step-over-regexp", 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in."}, +{ LLDB_OPT_SET_1, false, "step-in-target", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."}, +{ LLDB_OPT_SET_2, false, "python-class", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step."}, { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; @@ -860,17 +904,25 @@ public: } } + + StreamString stream; + Error error; + if (synchronous_execution) + error = process->ResumeSynchronous (&stream); + else + error = process->Resume (); + // We should not be holding the thread list lock when we do this. - Error error (process->Resume()); if (error.Success()) { result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); if (synchronous_execution) { - state = process->WaitForProcessToStop (NULL); + // If any state changed events had anything to say, add that to the result + if (stream.GetData()) + result.AppendMessage(stream.GetData()); result.SetDidChangeProcessState (true); - result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else @@ -1191,17 +1243,27 @@ protected: } + + process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx); - Error error (process->Resume ()); + + StreamString stream; + Error error; + if (synchronous_execution) + error = process->ResumeSynchronous (&stream); + else + error = process->Resume (); + if (error.Success()) { result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); if (synchronous_execution) { - StateType state = process->WaitForProcessToStop (NULL); + // If any state changed events had anything to say, add that to the result + if (stream.GetData()) + result.AppendMessage(stream.GetData()); result.SetDidChangeProcessState (true); - result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else @@ -1358,32 +1420,22 @@ protected: // CommandObjectThreadInfo //------------------------------------------------------------------------- -class CommandObjectThreadInfo : public CommandObjectParsed +class CommandObjectThreadInfo : public CommandObjectIterateOverThreads { public: CommandObjectThreadInfo (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "thread info", - "Show an extended summary of information about thread(s) in a process.", - "thread info", - eFlagRequiresProcess | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused), + CommandObjectIterateOverThreads (interpreter, + "thread info", + "Show an extended summary of information about thread(s) in a process.", + "thread info", + eFlagRequiresProcess | + eFlagTryTargetAPILock | + eFlagProcessMustBeLaunched | + eFlagProcessMustBePaused), m_options (interpreter) { - CommandArgumentEntry arg; - CommandArgumentData thread_idx_arg; - - thread_idx_arg.arg_type = eArgTypeThreadIndex; - thread_idx_arg.arg_repetition = eArgRepeatStar; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (thread_idx_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); + m_add_return = false; } class CommandOptions : public Options @@ -1399,7 +1451,8 @@ public: void OptionParsingStarting () { - m_json = false; + m_json_thread = false; + m_json_stopinfo = false; } virtual @@ -1416,10 +1469,14 @@ public: switch (short_option) { case 'j': - m_json = true; + m_json_thread = true; + break; + + case 's': + m_json_stopinfo = true; break; - default: + default: return Error("invalid short option character '%c'", short_option); } @@ -1432,7 +1489,8 @@ public: return g_option_table; } - bool m_json; + bool m_json_thread; + bool m_json_stopinfo; static OptionDefinition g_option_table[]; }; @@ -1451,81 +1509,16 @@ public: } virtual bool - DoExecute (Args& command, CommandReturnObject &result) + HandleOneThread (Thread &thread, CommandReturnObject &result) { - result.SetStatus (eReturnStatusSuccessFinishResult); Stream &strm = result.GetOutputStream(); - - if (command.GetArgumentCount() == 0) - { - Thread *thread = m_exe_ctx.GetThreadPtr(); - if (thread->GetDescription (strm, eDescriptionLevelFull, m_options.m_json)) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - } - } - else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0) - { - Process *process = m_exe_ctx.GetProcessPtr(); - uint32_t idx = 0; - for (ThreadSP thread_sp : process->Threads()) - { - if (idx != 0) - result.AppendMessage(""); - if (!thread_sp->GetDescription (strm, eDescriptionLevelFull, m_options.m_json)) - { - result.AppendErrorWithFormat ("error displaying info for thread: \"0x%4.4x\"\n", idx); - result.SetStatus (eReturnStatusFailed); - return false; - } - ++idx; - } - } - else + if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo)) { - const size_t num_args = command.GetArgumentCount(); - Process *process = m_exe_ctx.GetProcessPtr(); - Mutex::Locker locker (process->GetThreadList().GetMutex()); - std::vector thread_sps; - - for (size_t i = 0; i < num_args; i++) - { - bool success; - - uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success); - if (!success) - { - result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); - result.SetStatus (eReturnStatusFailed); - return false; - } - - thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx)); - - if (!thread_sps[i]) - { - result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i)); - result.SetStatus (eReturnStatusFailed); - return false; - } - - } - - for (uint32_t i = 0; i < num_args; i++) - { - if (!thread_sps[i]->GetDescription (strm, eDescriptionLevelFull, m_options.m_json)) - { - result.AppendErrorWithFormat ("error displaying info for thread: \"%s\"\n", command.GetArgumentAtIndex(i)); - result.SetStatus (eReturnStatusFailed); - return false; - } - - if (i < num_args - 1) - result.AppendMessage(""); - } - + result.AppendErrorWithFormat ("error displaying info for thread: \"%d\"\n", thread.GetIndexID()); + result.SetStatus (eReturnStatusFailed); + return false; } - return result.Succeeded(); + return true; } CommandOptions m_options; @@ -1536,6 +1529,7 @@ OptionDefinition CommandObjectThreadInfo::CommandOptions::g_option_table[] = { { LLDB_OPT_SET_ALL, false, "json",'j', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the thread info in JSON format."}, + { LLDB_OPT_SET_ALL, false, "stop-info",'s', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the extended stop info in JSON format."}, { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; @@ -1957,6 +1951,228 @@ CommandObjectThreadJump::CommandOptions::g_option_table[] = { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; +//------------------------------------------------------------------------- +// Next are the subcommands of CommandObjectMultiwordThreadPlan +//------------------------------------------------------------------------- + + +//------------------------------------------------------------------------- +// CommandObjectThreadPlanList +//------------------------------------------------------------------------- +class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads +{ +public: + + class CommandOptions : public Options + { + public: + + CommandOptions (CommandInterpreter &interpreter) : + Options(interpreter) + { + // Keep default values of all options in one place: OptionParsingStarting () + OptionParsingStarting (); + } + + virtual + ~CommandOptions () + { + } + + virtual Error + SetOptionValue (uint32_t option_idx, const char *option_arg) + { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) + { + case 'i': + { + m_internal = true; + } + break; + case 'v': + { + m_verbose = true; + } + break; + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); + break; + + } + return error; + } + + void + OptionParsingStarting () + { + m_verbose = false; + m_internal = false; + } + + const OptionDefinition* + GetDefinitions () + { + return g_option_table; + } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + bool m_verbose; + bool m_internal; + }; + + CommandObjectThreadPlanList (CommandInterpreter &interpreter) : + CommandObjectIterateOverThreads (interpreter, + "thread plan list", + "Show thread plans for one or more threads. If no threads are specified, show the " + "currently selected thread. Use the thread-index \"all\" to see all threads.", + NULL, + eFlagRequiresProcess | + eFlagRequiresThread | + eFlagTryTargetAPILock | + eFlagProcessMustBeLaunched | + eFlagProcessMustBePaused ), + m_options(interpreter) + { + } + + ~CommandObjectThreadPlanList () + { + } + + virtual Options * + GetOptions () + { + return &m_options; + } + +protected: + virtual bool + HandleOneThread (Thread &thread, CommandReturnObject &result) + { + Stream &strm = result.GetOutputStream(); + DescriptionLevel desc_level = eDescriptionLevelFull; + if (m_options.m_verbose) + desc_level = eDescriptionLevelVerbose; + + thread.DumpThreadPlans (&strm, desc_level, m_options.m_internal, true); + return true; + } + CommandOptions m_options; +}; + +OptionDefinition +CommandObjectThreadPlanList::CommandOptions::g_option_table[] = +{ +{ LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display more information about the thread plans"}, +{ LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display internal as well as user thread plans"}, +{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } +}; + +class CommandObjectThreadPlanDiscard : public CommandObjectParsed +{ +public: + CommandObjectThreadPlanDiscard (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "thread plan discard", + "Discards thread plans up to and including the plan passed as the command argument." + "Only user visible plans can be discarded, use the index from \"thread plan list\"" + " without the \"-i\" argument.", + NULL, + eFlagRequiresProcess | + eFlagRequiresThread | + eFlagTryTargetAPILock | + eFlagProcessMustBeLaunched | + eFlagProcessMustBePaused ) + { + CommandArgumentEntry arg; + CommandArgumentData plan_index_arg; + + // Define the first (and only) variant of this arg. + plan_index_arg.arg_type = eArgTypeUnsignedInteger; + plan_index_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the argument entry. + arg.push_back (plan_index_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back (arg); + } + + virtual ~CommandObjectThreadPlanDiscard () {} + + bool + DoExecute (Args& args, CommandReturnObject &result) + { + Thread *thread = m_exe_ctx.GetThreadPtr(); + if (args.GetArgumentCount() != 1) + { + result.AppendErrorWithFormat("Too many arguments, expected one - the thread plan index - but got %zu.", + args.GetArgumentCount()); + result.SetStatus (eReturnStatusFailed); + return false; + } + + bool success; + uint32_t thread_plan_idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success); + if (!success) + { + 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; + } + + if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) + { + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return true; + } + else + { + result.AppendErrorWithFormat("Could not find User thread plan with index %s.", + args.GetArgumentAtIndex(0)); + result.SetStatus (eReturnStatusFailed); + return false; + } + } +}; + +//------------------------------------------------------------------------- +// CommandObjectMultiwordThreadPlan +//------------------------------------------------------------------------- + +class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword +{ +public: + CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) : + CommandObjectMultiword (interpreter, + "plan", + "A set of subcommands for accessing the thread plans controlling execution control on one or more threads.", + "thread plan [ // C++ Includes +#include #include "llvm/ADT/StringRef.h" @@ -31,6 +32,11 @@ #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/OptionGroupFormat.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadList.h" using namespace lldb; using namespace lldb_private; @@ -2465,22 +2471,7 @@ protected: if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0) { - // we want to make sure to enable "system" last and "default" first - DataVisualization::Categories::Enable(ConstString("default"), TypeCategoryMap::First); - uint32_t num_categories = DataVisualization::Categories::GetCount(); - for (uint32_t i = 0; i < num_categories; i++) - { - lldb::TypeCategoryImplSP category_sp = DataVisualization::Categories::GetCategoryAtIndex(i); - if (category_sp) - { - if ( ::strcmp(category_sp->GetName(), "system") == 0 || - ::strcmp(category_sp->GetName(), "default") == 0 ) - continue; - else - DataVisualization::Categories::Enable(category_sp, TypeCategoryMap::Default); - } - } - DataVisualization::Categories::Enable(ConstString("system"), TypeCategoryMap::Last); + DataVisualization::Categories::EnableStar(); } else { @@ -2630,14 +2621,7 @@ protected: if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0) { - uint32_t num_categories = DataVisualization::Categories::GetCount(); - for (uint32_t i = 0; i < num_categories; i++) - { - lldb::TypeCategoryImplSP category_sp = DataVisualization::Categories::GetCategoryAtIndex(i); - // no need to check if the category is enabled - disabling a disabled category has no effect - if (category_sp) - DataVisualization::Categories::Disable(category_sp); - } + DataVisualization::Categories::DisableStar(); } else { @@ -4253,6 +4237,84 @@ CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] = { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; +template +class CommandObjectFormatterInfo : public CommandObjectRaw +{ +public: + typedef std::function DiscoveryFunction; + CommandObjectFormatterInfo (CommandInterpreter &interpreter, + const char* formatter_name, + DiscoveryFunction discovery_func) : + CommandObjectRaw(interpreter, + nullptr, + nullptr, + nullptr, + eFlagRequiresFrame), + m_formatter_name(formatter_name ? formatter_name : ""), + m_discovery_function(discovery_func) + { + StreamString name; + name.Printf("type %s info", formatter_name); + SetCommandName(name.GetData()); + StreamString help; + help.Printf("This command evaluates the provided expression and shows which %s is applied to the resulting value (if any).", formatter_name); + SetHelp(help.GetData()); + StreamString syntax; + syntax.Printf("type %s info ", formatter_name); + SetSyntax(syntax.GetData()); + } + + virtual + ~CommandObjectFormatterInfo () + { + } + +protected: + virtual bool + DoExecute (const char *command, CommandReturnObject &result) + { + auto target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); + auto frame_sp = target_sp->GetProcessSP()->GetThreadList().GetSelectedThread()->GetSelectedFrame(); + ValueObjectSP result_valobj_sp; + EvaluateExpressionOptions options; + lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(command, frame_sp.get(), result_valobj_sp, options); + if (expr_result == eExpressionCompleted && result_valobj_sp) + { + result_valobj_sp = result_valobj_sp->GetQualifiedRepresentationIfAvailable(target_sp->GetPreferDynamicValue(), target_sp->GetEnableSyntheticValue()); + typename FormatterType::SharedPointer formatter_sp = m_discovery_function(*result_valobj_sp); + if (formatter_sp) + { + std::string description(formatter_sp->GetDescription()); + result.AppendMessageWithFormat("%s applied to (%s) %s is: %s\n", + m_formatter_name.c_str(), + result_valobj_sp->GetDisplayTypeName().AsCString(""), + command, + description.c_str()); + result.SetStatus(lldb::eReturnStatusSuccessFinishResult); + } + else + { + result.AppendMessageWithFormat("no %s applies to (%s) %s\n", + m_formatter_name.c_str(), + result_valobj_sp->GetDisplayTypeName().AsCString(""), + command); + result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); + } + return true; + } + else + { + result.AppendError("failed to evaluate expression"); + result.SetStatus(lldb::eReturnStatusFailed); + return false; + } + } + +private: + std::string m_formatter_name; + DiscoveryFunction m_discovery_function; +}; + class CommandObjectTypeFormat : public CommandObjectMultiword { public: @@ -4266,6 +4328,11 @@ public: LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFormatClear (interpreter))); LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter))); LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFormatList (interpreter))); + LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo(interpreter, + "format", + [](ValueObject& valobj) -> TypeFormatImpl::SharedPointer { + return valobj.GetValueFormat(); + }))); } @@ -4289,6 +4356,11 @@ public: LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSynthClear (interpreter))); LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter))); LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSynthList (interpreter))); + LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo(interpreter, + "synthetic", + [](ValueObject& valobj) -> SyntheticChildren::SharedPointer { + return valobj.GetSyntheticChildren(); + }))); } @@ -4354,6 +4426,11 @@ public: LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); + LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo(interpreter, + "summary", + [](ValueObject& valobj) -> TypeSummaryImpl::SharedPointer { + return valobj.GetSummaryFormat(); + }))); } diff --git a/source/Commands/CommandObjectWatchpointCommand.cpp b/source/Commands/CommandObjectWatchpointCommand.cpp index f46db7a6a82b..275ee925adcc 100644 --- a/source/Commands/CommandObjectWatchpointCommand.cpp +++ b/source/Commands/CommandObjectWatchpointCommand.cpp @@ -279,17 +279,16 @@ but do NOT enter more than one command per line. \n" ); result.SetImmediateOutputStream (output_stream); result.SetImmediateErrorStream (error_stream); - bool stop_on_continue = true; - bool echo_commands = false; - bool print_results = true; + CommandInterpreterRunOptions options; + options.SetStopOnContinue (true); + options.SetStopOnError (data->stop_on_error); + options.SetEchoCommands (false); + options.SetPrintResults (true); + options.SetAddToHistory (false); debugger.GetCommandInterpreter().HandleCommands (commands, &exe_ctx, - stop_on_continue, - data->stop_on_error, - echo_commands, - print_results, - eLazyBoolNo, + options, result); result.GetImmediateOutputStream()->Flush(); result.GetImmediateErrorStream()->Flush(); diff --git a/source/Core/Address.cpp b/source/Core/Address.cpp index fa9197d12b70..a79becbf49c4 100644 --- a/source/Core/Address.cpp +++ b/source/Core/Address.cpp @@ -433,7 +433,9 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum case DumpStyleModuleWithFileAddress: if (section_sp) - s->Printf("%s[", section_sp->GetModule()->GetFileSpec().GetFilename().AsCString()); + { + s->Printf("%s[", section_sp->GetModule()->GetFileSpec().GetFilename().AsCString("")); + } // Fall through case DumpStyleFileAddress: { @@ -465,6 +467,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum case DumpStyleResolvedDescription: case DumpStyleResolvedDescriptionNoModule: + case DumpStyleResolvedDescriptionNoFunctionArguments: if (IsSectionOffset()) { uint32_t pointer_size = 4; @@ -550,7 +553,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum #endif Address cstr_addr(*this); cstr_addr.SetOffset(cstr_addr.GetOffset() + pointer_size); - func_sc.DumpStopContext(s, exe_scope, so_addr, true, true, false); + func_sc.DumpStopContext(s, exe_scope, so_addr, true, true, false, true); if (ReadAddress (exe_scope, cstr_addr, pointer_size, so_addr)) { #if VERBOSE_OUTPUT @@ -633,7 +636,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum if (pointer_sc.function || pointer_sc.symbol) { s->PutCString(": "); - pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false, false); + pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false, false, true); } } } @@ -658,6 +661,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum const bool show_module = (style == DumpStyleResolvedDescription); const bool show_fullpaths = false; const bool show_inlined_frames = true; + const bool show_function_arguments = (style != DumpStyleResolvedDescriptionNoFunctionArguments); if (sc.function == NULL && sc.symbol != NULL) { // If we have just a symbol make sure it is in the right section @@ -679,7 +683,8 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum *this, show_fullpaths, show_module, - show_inlined_frames); + show_inlined_frames, + show_function_arguments); } else { diff --git a/source/Core/AddressRange.cpp b/source/Core/AddressRange.cpp index 3505d56b43e2..ac64833884ee 100644 --- a/source/Core/AddressRange.cpp +++ b/source/Core/AddressRange.cpp @@ -179,7 +179,7 @@ AddressRange::Dump(Stream *s, Target *target, Address::DumpStyle style, Address: { ModuleSP module_sp (GetBaseAddress().GetModule()); if (module_sp) - s->Printf("%s", module_sp->GetFileSpec().GetFilename().AsCString()); + s->Printf("%s", module_sp->GetFileSpec().GetFilename().AsCString("")); } s->AddressRange(vmaddr, vmaddr + GetByteSize(), addr_size); return true; diff --git a/source/Core/AddressResolverFileLine.cpp b/source/Core/AddressResolverFileLine.cpp index f7004c8bb089..6089abd76cbc 100644 --- a/source/Core/AddressResolverFileLine.cpp +++ b/source/Core/AddressResolverFileLine.cpp @@ -96,7 +96,7 @@ AddressResolverFileLine::GetDepth() void AddressResolverFileLine::GetDescription (Stream *s) { - s->Printf ("File and line address - file: \"%s\" line: %u", m_file_spec.GetFilename().AsCString(), m_line_number); + s->Printf ("File and line address - file: \"%s\" line: %u", m_file_spec.GetFilename().AsCString(""), m_line_number); } diff --git a/source/Core/ArchSpec.cpp b/source/Core/ArchSpec.cpp index 5f010f066408..e7a5e489af19 100644 --- a/source/Core/ArchSpec.cpp +++ b/source/Core/ArchSpec.cpp @@ -24,6 +24,11 @@ #include "lldb/Host/Endian.h" #include "lldb/Host/HostInfo.h" #include "lldb/Target/Platform.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Thread.h" +#include "Plugins/Process/Utility/ARMDefines.h" +#include "Plugins/Process/Utility/InstructionUtils.h" using namespace lldb; using namespace lldb_private; @@ -84,7 +89,7 @@ static const CoreDefinition g_core_definitions[] = { eByteOrderBig , 8, 4, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64 , "mips64" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_generic , "ppc" }, + { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_generic , "powerpc" }, { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc601 , "ppc601" }, { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc602 , "ppc602" }, { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc603 , "ppc603" }, @@ -98,7 +103,7 @@ static const CoreDefinition g_core_definitions[] = { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc7450 , "ppc7450" }, { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc970 , "ppc970" }, - { eByteOrderBig , 8, 4, 4, llvm::Triple::ppc64 , ArchSpec::eCore_ppc64_generic , "ppc64" }, + { eByteOrderBig , 8, 4, 4, llvm::Triple::ppc64 , ArchSpec::eCore_ppc64_generic , "powerpc64" }, { eByteOrderBig , 8, 4, 4, llvm::Triple::ppc64 , ArchSpec::eCore_ppc64_ppc970_64 , "ppc970-64" }, { eByteOrderLittle, 4, 4, 4, llvm::Triple::sparc , ArchSpec::eCore_sparc_generic , "sparc" }, @@ -118,7 +123,6 @@ static const CoreDefinition g_core_definitions[] = { eByteOrderLittle, 4, 4, 4 , llvm::Triple::UnknownArch , ArchSpec::eCore_uknownMach32 , "unknown-mach-32" }, { eByteOrderLittle, 8, 4, 4 , llvm::Triple::UnknownArch , ArchSpec::eCore_uknownMach64 , "unknown-mach-64" }, - { eByteOrderLittle, 4, 1, 1 , llvm::Triple::kalimba , ArchSpec::eCore_kalimba , "kalimba" }, { eByteOrderBig , 4, 1, 1 , llvm::Triple::kalimba , ArchSpec::eCore_kalimba3 , "kalimba3" }, { eByteOrderLittle, 4, 1, 1 , llvm::Triple::kalimba , ArchSpec::eCore_kalimba4 , "kalimba4" }, { eByteOrderLittle, 4, 1, 1 , llvm::Triple::kalimba , ArchSpec::eCore_kalimba5 , "kalimba5" } @@ -195,10 +199,10 @@ static const ArchDefinitionEntry g_macho_arch_entries[] = { ArchSpec::eCore_arm_armv7k , llvm::MachO::CPU_TYPE_ARM , 12 , UINT32_MAX , SUBTYPE_MASK }, { ArchSpec::eCore_arm_armv7m , llvm::MachO::CPU_TYPE_ARM , 15 , UINT32_MAX , SUBTYPE_MASK }, { ArchSpec::eCore_arm_armv7em , llvm::MachO::CPU_TYPE_ARM , 16 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_arm64 , llvm::MachO::CPU_TYPE_ARM64 , CPU_ANY, UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_arm64 , llvm::MachO::CPU_TYPE_ARM64 , 0 , UINT32_MAX , SUBTYPE_MASK }, { ArchSpec::eCore_arm_arm64 , llvm::MachO::CPU_TYPE_ARM64 , 1 , UINT32_MAX , SUBTYPE_MASK }, + { ArchSpec::eCore_arm_arm64 , llvm::MachO::CPU_TYPE_ARM64 , 0 , UINT32_MAX , SUBTYPE_MASK }, { ArchSpec::eCore_arm_arm64 , llvm::MachO::CPU_TYPE_ARM64 , 13 , UINT32_MAX , SUBTYPE_MASK }, + { ArchSpec::eCore_arm_arm64 , llvm::MachO::CPU_TYPE_ARM64 , CPU_ANY, UINT32_MAX , SUBTYPE_MASK }, { ArchSpec::eCore_thumb , llvm::MachO::CPU_TYPE_ARM , 0 , UINT32_MAX , SUBTYPE_MASK }, { ArchSpec::eCore_thumbv4t , llvm::MachO::CPU_TYPE_ARM , 5 , UINT32_MAX , SUBTYPE_MASK }, { ArchSpec::eCore_thumbv5 , llvm::MachO::CPU_TYPE_ARM , 7 , UINT32_MAX , SUBTYPE_MASK }, @@ -264,11 +268,9 @@ static const ArchDefinitionEntry g_elf_arch_entries[] = { ArchSpec::eCore_x86_64_x86_64 , llvm::ELF::EM_X86_64 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // AMD64 { ArchSpec::eCore_mips64 , llvm::ELF::EM_MIPS , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // MIPS { ArchSpec::eCore_hexagon_generic , llvm::ELF::EM_HEXAGON, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // HEXAGON - { ArchSpec::eCore_kalimba , llvm::ELF::EM_CSR_KALIMBA, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // KALIMBA - { ArchSpec::eCore_kalimba3 , llvm::ELF::EM_CSR_KALIMBA, 3, 0xFFFFFFFFu, 0xFFFFFFFFu }, // KALIMBA - { ArchSpec::eCore_kalimba4 , llvm::ELF::EM_CSR_KALIMBA, 4, 0xFFFFFFFFu, 0xFFFFFFFFu }, // KALIMBA - { ArchSpec::eCore_kalimba5 , llvm::ELF::EM_CSR_KALIMBA, 5, 0xFFFFFFFFu, 0xFFFFFFFFu } // KALIMBA - + { ArchSpec::eCore_kalimba3 , llvm::ELF::EM_CSR_KALIMBA, llvm::Triple::KalimbaSubArch_v3, 0xFFFFFFFFu, 0xFFFFFFFFu }, // KALIMBA + { ArchSpec::eCore_kalimba4 , llvm::ELF::EM_CSR_KALIMBA, llvm::Triple::KalimbaSubArch_v4, 0xFFFFFFFFu, 0xFFFFFFFFu }, // KALIMBA + { ArchSpec::eCore_kalimba5 , llvm::ELF::EM_CSR_KALIMBA, llvm::Triple::KalimbaSubArch_v5, 0xFFFFFFFFu, 0xFFFFFFFFu } // KALIMBA }; static const ArchDefinition g_elf_arch_def = { @@ -503,11 +505,11 @@ ArchSpec::GetDataByteSize () const switch (m_core) { case eCore_kalimba3: - return 3; + return 4; case eCore_kalimba4: return 1; case eCore_kalimba5: - return 3; + return 4; default: return 1; } @@ -1036,16 +1038,6 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in } break; - case ArchSpec::eCore_kalimba: - case ArchSpec::eCore_kalimba3: - case ArchSpec::eCore_kalimba4: - case ArchSpec::eCore_kalimba5: - if (core2 >= ArchSpec::kCore_kalimba_first && core2 <= ArchSpec::kCore_kalimba_last) - { - return true; - } - break; - case ArchSpec::eCore_arm_armv8: if (!enforce_exact_match) { @@ -1094,3 +1086,108 @@ lldb_private::operator<(const ArchSpec& lhs, const ArchSpec& rhs) const ArchSpec::Core rhs_core = rhs.GetCore (); return lhs_core < rhs_core; } + +static void +StopInfoOverrideCallbackTypeARM(lldb_private::Thread &thread) +{ + // We need to check if we are stopped in Thumb mode in a IT instruction + // and detect if the condition doesn't pass. If this is the case it means + // we won't actually execute this instruction. If this happens we need to + // clear the stop reason to no thread plans think we are stopped for a + // reason and the plans should keep going. + // + // We do this because when single stepping many ARM processes, debuggers + // often use the BVR/BCR registers that says "stop when the PC is not + // equal to its current value". This method of stepping means we can end + // up stopping on instructions inside an if/then block that wouldn't get + // executed. By fixing this we can stop the debugger from seeming like + // you stepped through both the "if" _and_ the "else" clause when source + // level stepping because the debugger stops regardless due to the BVR/BCR + // triggering a stop. + // + // It also means we can set breakpoints on instructions inside an an + // if/then block and correctly skip them if we use the BKPT instruction. + // The ARM and Thumb BKPT instructions are unconditional even when executed + // in a Thumb IT block. + // + // If your debugger inserts software traps in ARM/Thumb code, it will + // need to use 16 and 32 bit instruction for 16 and 32 bit thumb + // instructions respectively. If your debugger inserts a 16 bit thumb + // trap on top of a 32 bit thumb instruction for an opcode that is inside + // an if/then, it will change the it/then to conditionally execute your + // 16 bit trap and then cause your program to crash if it executes the + // trailing 16 bits (the second half of the 32 bit thumb instruction you + // partially overwrote). + + RegisterContextSP reg_ctx_sp (thread.GetRegisterContext()); + if (reg_ctx_sp) + { + const uint32_t cpsr = reg_ctx_sp->GetFlags(0); + if (cpsr != 0) + { + // Read the J and T bits to get the ISETSTATE + const uint32_t J = Bit32(cpsr, 24); + const uint32_t T = Bit32(cpsr, 5); + const uint32_t ISETSTATE = J << 1 | T; + if (ISETSTATE == 0) + { + // NOTE: I am pretty sure we want to enable the code below + // that detects when we stop on an instruction in ARM mode + // that is conditional and the condition doesn't pass. This + // can happen if you set a breakpoint on an instruction that + // is conditional. We currently will _always_ stop on the + // instruction which is bad. You can also run into this while + // single stepping and you could appear to run code in the "if" + // and in the "else" clause because it would stop at all of the + // conditional instructions in both. + // In such cases, we really don't want to stop at this location. + // I will check with the lldb-dev list first before I enable this. +#if 0 + // ARM mode: check for condition on intsruction + const addr_t pc = reg_ctx_sp->GetPC(); + Error error; + // If we fail to read the opcode we will get UINT64_MAX as the + // result in "opcode" which we can use to detect if we read a + // valid opcode. + const uint64_t opcode = thread.GetProcess()->ReadUnsignedIntegerFromMemory(pc, 4, UINT64_MAX, error); + if (opcode <= UINT32_MAX) + { + const uint32_t condition = Bits32((uint32_t)opcode, 31, 28); + if (ARMConditionPassed(condition, cpsr) == false) + { + // We ARE stopped on an ARM instruction whose condition doesn't + // pass so this instruction won't get executed. + // Regardless of why it stopped, we need to clear the stop info + thread.SetStopInfo (StopInfoSP()); + } + } +#endif + } + else if (ISETSTATE == 1) + { + // Thumb mode + const uint32_t ITSTATE = Bits32 (cpsr, 15, 10) << 2 | Bits32 (cpsr, 26, 25); + if (ITSTATE != 0) + { + const uint32_t condition = Bits32(ITSTATE, 7, 4); + if (ARMConditionPassed(condition, cpsr) == false) + { + // We ARE stopped in a Thumb IT instruction on an instruction whose + // condition doesn't pass so this instruction won't get executed. + // Regardless of why it stopped, we need to clear the stop info + thread.SetStopInfo (StopInfoSP()); + } + } + } + } + } +} + +ArchSpec::StopInfoOverrideCallbackType +ArchSpec::GetStopInfoOverrideCallback () const +{ + const llvm::Triple::ArchType machine = GetMachine(); + if (machine == llvm::Triple::arm) + return StopInfoOverrideCallbackTypeARM; + return NULL; +} diff --git a/source/Core/Communication.cpp b/source/Core/Communication.cpp index d71c9881a6f3..ea84843fe0b3 100644 --- a/source/Core/Communication.cpp +++ b/source/Core/Communication.cpp @@ -18,6 +18,8 @@ #include "lldb/Core/Timer.h" #include "lldb/Core/Event.h" #include "lldb/Host/Host.h" +#include "lldb/Host/HostThread.h" +#include "lldb/Host/ThreadLauncher.h" #include using namespace lldb; @@ -36,7 +38,6 @@ Communication::GetStaticBroadcasterClass () Communication::Communication(const char *name) : Broadcaster (NULL, name), m_connection_sp (), - m_read_thread (LLDB_INVALID_HOST_THREAD), m_read_thread_enabled (false), m_bytes(), m_bytes_mutex (Mutex::eMutexTypeRecursive), @@ -232,7 +233,7 @@ Communication::StartReadThread (Error *error_ptr) if (error_ptr) error_ptr->Clear(); - if (IS_VALID_LLDB_HOST_THREAD(m_read_thread)) + if (m_read_thread.IsJoinable()) return true; lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, @@ -243,8 +244,8 @@ Communication::StartReadThread (Error *error_ptr) snprintf(thread_name, sizeof(thread_name), "", m_broadcaster_name.AsCString()); m_read_thread_enabled = true; - m_read_thread = Host::ThreadCreate (thread_name, Communication::ReadThread, this, error_ptr); - if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread)) + m_read_thread = ThreadLauncher::LaunchThread(thread_name, Communication::ReadThread, this, error_ptr); + if (!m_read_thread.IsJoinable()) m_read_thread_enabled = false; return m_read_thread_enabled; } @@ -252,7 +253,7 @@ Communication::StartReadThread (Error *error_ptr) bool Communication::StopReadThread (Error *error_ptr) { - if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread)) + if (!m_read_thread.IsJoinable()) return true; lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, @@ -262,22 +263,20 @@ Communication::StopReadThread (Error *error_ptr) BroadcastEvent (eBroadcastBitReadThreadShouldExit, NULL); - //Host::ThreadCancel (m_read_thread, error_ptr); + // error = m_read_thread.Cancel(); - bool status = Host::ThreadJoin (m_read_thread, NULL, error_ptr); - m_read_thread = LLDB_INVALID_HOST_THREAD; - return status; + Error error = m_read_thread.Join(nullptr); + return error.Success(); } bool Communication::JoinReadThread (Error *error_ptr) { - if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread)) + if (!m_read_thread.IsJoinable()) return true; - bool success = Host::ThreadJoin (m_read_thread, NULL, error_ptr); - m_read_thread = LLDB_INVALID_HOST_THREAD; - return success; + Error error = m_read_thread.Join(nullptr); + return error.Success(); } size_t diff --git a/source/Core/Connection.cpp b/source/Core/Connection.cpp index 3c9bb8b1b7ed..3f740a1ed82a 100644 --- a/source/Core/Connection.cpp +++ b/source/Core/Connection.cpp @@ -13,6 +13,12 @@ // Project includes #include "lldb/Core/Connection.h" +#if defined(_WIN32) +#include "lldb/Host/windows/ConnectionGenericFileWindows.h" +#endif + +#include "lldb/Host/ConnectionFileDescriptor.h" + using namespace lldb_private; Connection::Connection () @@ -22,3 +28,13 @@ Connection::Connection () Connection::~Connection () { } + +Connection * +Connection::CreateDefaultConnection(const char *url) +{ +#if defined(_WIN32) + if (strstr(url, "file://") == url) + return new ConnectionGenericFile(); +#endif + return new ConnectionFileDescriptor(); +} diff --git a/source/Core/ConnectionFileDescriptor.cpp b/source/Core/ConnectionFileDescriptor.cpp deleted file mode 100644 index 7c8e98a21129..000000000000 --- a/source/Core/ConnectionFileDescriptor.cpp +++ /dev/null @@ -1,815 +0,0 @@ -//===-- ConnectionFileDescriptor.cpp ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#if defined(__APPLE__) -// Enable this special support for Apple builds where we can have unlimited -// select bounds. We tried switching to poll() and kqueue and we were panicing -// the kernel, so we have to stick with select for now. -#define _DARWIN_UNLIMITED_SELECT -#endif - -#include "lldb/Core/ConnectionFileDescriptor.h" -#include "lldb/Host/Config.h" -#include "lldb/Host/IOObject.h" -#include "lldb/Host/SocketAddress.h" -#include "lldb/Host/Socket.h" - -// C Includes -#include -#include -#include -#include -#include - -#ifndef LLDB_DISABLE_POSIX -#include -#endif - -// C++ Includes -// Other libraries and framework includes -#include "llvm/Support/ErrorHandling.h" -#if defined(__APPLE__) -#include "llvm/ADT/SmallVector.h" -#endif -// Project includes -#include "lldb/lldb-private-log.h" -#include "lldb/Core/Communication.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/Timer.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/Socket.h" -#include "lldb/Interpreter/Args.h" - - -using namespace lldb; -using namespace lldb_private; - -ConnectionFileDescriptor::ConnectionFileDescriptor () : - Connection(), - m_pipe (), - m_mutex (Mutex::eMutexTypeRecursive), - m_shutting_down (false), - m_waiting_for_accept (false) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf ("%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", - static_cast(this)); -} - -ConnectionFileDescriptor::ConnectionFileDescriptor (int fd, bool owns_fd) : - Connection(), - m_pipe (), - m_mutex (Mutex::eMutexTypeRecursive), - m_shutting_down (false), - m_waiting_for_accept (false) -{ - m_write_sp.reset(new File(fd, owns_fd)); - m_read_sp.reset(new File(fd, false)); - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf ("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)", - static_cast(this), fd, owns_fd); - OpenCommandPipe (); -} - - -ConnectionFileDescriptor::~ConnectionFileDescriptor () -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf ("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", - static_cast(this)); - Disconnect (NULL); - CloseCommandPipe (); -} - -void -ConnectionFileDescriptor::OpenCommandPipe () -{ - CloseCommandPipe(); - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); - // Make the command file descriptor here: - if (!m_pipe.Open()) - { - if (log) - log->Printf ("%p ConnectionFileDescriptor::OpenCommandPipe () - could not make pipe: %s", - static_cast(this), strerror(errno)); - } - else - { - if (log) - log->Printf ("%p ConnectionFileDescriptor::OpenCommandPipe() - success readfd=%d writefd=%d", - static_cast(this), - m_pipe.GetReadFileDescriptor(), - m_pipe.GetWriteFileDescriptor()); - } -} - -void -ConnectionFileDescriptor::CloseCommandPipe () -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf ("%p ConnectionFileDescriptor::CloseCommandPipe()", - static_cast(this)); - - m_pipe.Close(); -} - -bool -ConnectionFileDescriptor::IsConnected () const -{ - return (m_read_sp && m_read_sp->IsValid()) || (m_write_sp && m_write_sp->IsValid()); -} - -ConnectionStatus -ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr) -{ - Mutex::Locker locker (m_mutex); - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf ("%p ConnectionFileDescriptor::Connect (url = '%s')", - static_cast(this), s); - - OpenCommandPipe(); - - if (s && s[0]) - { - if (strstr(s, "listen://") == s) - { - // listen://HOST:PORT - return SocketListen (s + strlen("listen://"), error_ptr); - } - else if (strstr(s, "accept://") == s) - { - // unix://SOCKNAME - return NamedSocketAccept (s + strlen("accept://"), error_ptr); - } - else if (strstr(s, "unix-accept://") == s) - { - // unix://SOCKNAME - return NamedSocketAccept (s + strlen("unix-accept://"), error_ptr); - } - else if (strstr(s, "connect://") == s) - { - return ConnectTCP (s + strlen("connect://"), error_ptr); - } - else if (strstr(s, "tcp-connect://") == s) - { - return ConnectTCP (s + strlen("tcp-connect://"), error_ptr); - } - else if (strstr(s, "udp://") == s) - { - return ConnectUDP (s + strlen("udp://"), error_ptr); - } -#ifndef LLDB_DISABLE_POSIX - else if (strstr(s, "fd://") == s) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("Protocol is not supported on non-posix hosts '%s'", s); - return eConnectionStatusError; - // Just passing a native file descriptor within this current process - // that is already opened (possibly from a service or other source). - s += strlen ("fd://"); - bool success = false; - int fd = Args::StringToSInt32 (s, -1, 0, &success); - - if (success) - { - // We have what looks to be a valid file descriptor, but we - // should make sure it is. We currently are doing this by trying to - // get the flags from the file descriptor and making sure it - // isn't a bad fd. - errno = 0; - int flags = ::fcntl (fd, F_GETFL, 0); - if (flags == -1 || errno == EBADF) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("stale file descriptor: %s", s); - m_read_sp.reset(); - m_write_sp.reset(); - return eConnectionStatusError; - } - else - { - // Don't take ownership of a file descriptor that gets passed - // to us since someone else opened the file descriptor and - // handed it to us. - // TODO: Since are using a URL to open connection we should - // eventually parse options using the web standard where we - // have "fd://123?opt1=value;opt2=value" and we can have an - // option be "owns=1" or "owns=0" or something like this to - // allow us to specify this. For now, we assume we must - // assume we don't own it. - - std::unique_ptr tcp_socket; - tcp_socket.reset(new Socket(fd, Socket::ProtocolTcp, false)); - // Try and get a socket option from this file descriptor to - // see if this is a socket and set m_is_socket accordingly. - int resuse; - bool is_socket = !!tcp_socket->GetOption(SOL_SOCKET, SO_REUSEADDR, resuse); - if (is_socket) - { - m_read_sp = std::move(tcp_socket); - m_write_sp = m_read_sp; - } - else - { - m_read_sp.reset(new File(fd, false)); - m_write_sp.reset(new File(fd, false)); - } - return eConnectionStatusSuccess; - } - } - - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("invalid file descriptor: \"fd://%s\"", s); - m_read_sp.reset(); - m_write_sp.reset(); - return eConnectionStatusError; - } - else if (strstr(s, "file://") == s) - { - // file:///PATH - const char *path = s + strlen("file://"); - int fd = -1; - do - { - fd = ::open (path, O_RDWR); - } while (fd == -1 && errno == EINTR); - - if (fd == -1) - { - if (error_ptr) - error_ptr->SetErrorToErrno(); - return eConnectionStatusError; - } - - if (::isatty(fd)) - { - // Set up serial terminal emulation - struct termios options; - ::tcgetattr (fd, &options); - - // Set port speed to maximum - ::cfsetospeed (&options, B115200); - ::cfsetispeed (&options, B115200); - - // Raw input, disable echo and signals - options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); - - // Make sure only one character is needed to return from a read - options.c_cc[VMIN] = 1; - options.c_cc[VTIME] = 0; - - ::tcsetattr (fd, TCSANOW, &options); - } - - int flags = ::fcntl (fd, F_GETFL, 0); - if (flags >= 0) - { - if ((flags & O_NONBLOCK) == 0) - { - flags |= O_NONBLOCK; - ::fcntl (fd, F_SETFL, flags); - } - } - m_read_sp.reset(new File(fd, true)); - m_write_sp.reset(new File(fd, false)); - return eConnectionStatusSuccess; - } -#endif - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("unsupported connection URL: '%s'", s); - return eConnectionStatusError; - } - if (error_ptr) - error_ptr->SetErrorString("invalid connect arguments"); - return eConnectionStatusError; -} - -bool -ConnectionFileDescriptor::InterruptRead() -{ - return m_pipe.Write("i", 1) == 1; -} - -ConnectionStatus -ConnectionFileDescriptor::Disconnect (Error *error_ptr) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf ("%p ConnectionFileDescriptor::Disconnect ()", - static_cast(this)); - - ConnectionStatus status = eConnectionStatusSuccess; - - if (!IsConnected()) - { - if (log) - log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", - static_cast(this)); - return eConnectionStatusSuccess; - } - - if (m_read_sp && m_read_sp->IsValid() && m_read_sp->GetFdType() == IOObject::eFDTypeSocket) - static_cast(*m_read_sp).PreDisconnect(); - - // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is quite likely - // because somebody is doing a blocking read on our file descriptor. If that's the case, - // then send the "q" char to the command file channel so the read will wake up and the connection - // will then know to shut down. - - m_shutting_down = true; - - Mutex::Locker locker; - bool got_lock = locker.TryLock (m_mutex); - - if (!got_lock) - { - if (m_pipe.WriteDescriptorIsValid()) - { - int result; - result = m_pipe.Write("q", 1) == 1; - if (log) - log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, sent 'q' to %d, result = %d.", - static_cast(this), m_pipe.GetWriteFileDescriptor(), result); - } - else if (log) - { - log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, but no command pipe is available.", - static_cast(this)); - } - locker.Lock (m_mutex); - } - - Error error = m_read_sp->Close(); - Error error2 = m_write_sp->Close(); - if (error.Fail() || error2.Fail()) - status = eConnectionStatusError; - if (error_ptr) - *error_ptr = error.Fail() ? error : error2; - - m_shutting_down = false; - return status; -} - -size_t -ConnectionFileDescriptor::Read (void *dst, - size_t dst_len, - uint32_t timeout_usec, - ConnectionStatus &status, - Error *error_ptr) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); - - Mutex::Locker locker; - bool got_lock = locker.TryLock (m_mutex); - if (!got_lock) - { - if (log) - log->Printf ("%p ConnectionFileDescriptor::Read () failed to get the connection lock.", - static_cast(this)); - if (error_ptr) - error_ptr->SetErrorString ("failed to get the connection lock for read."); - - status = eConnectionStatusTimedOut; - return 0; - } - else if (m_shutting_down) - return eConnectionStatusError; - - status = BytesAvailable (timeout_usec, error_ptr); - if (status != eConnectionStatusSuccess) - return 0; - - Error error; - size_t bytes_read = dst_len; - error = m_read_sp->Read(dst, bytes_read); - - if (log) - { - log->Printf("%p ConnectionFileDescriptor::Read() fd = %" PRIu64 ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s", - static_cast(this), - static_cast(m_read_sp->GetWaitableHandle()), - static_cast(dst), - static_cast(dst_len), - static_cast(bytes_read), - error.AsCString()); - } - - if (bytes_read == 0) - { - error.Clear(); // End-of-file. Do not automatically close; pass along for the end-of-file handlers. - status = eConnectionStatusEndOfFile; - } - - if (error_ptr) - *error_ptr = error; - - if (error.Fail()) - { - uint32_t error_value = error.GetError(); - switch (error_value) - { - case EAGAIN: // The file was marked for non-blocking I/O, and no data were ready to be read. - if (m_read_sp->GetFdType() == IOObject::eFDTypeSocket) - status = eConnectionStatusTimedOut; - else - status = eConnectionStatusSuccess; - return 0; - - case EFAULT: // Buf points outside the allocated address space. - case EINTR: // A read from a slow device was interrupted before any data arrived by the delivery of a signal. - case EINVAL: // The pointer associated with fildes was negative. - case EIO: // An I/O error occurred while reading from the file system. - // The process group is orphaned. - // The file is a regular file, nbyte is greater than 0, - // the starting position is before the end-of-file, and - // the starting position is greater than or equal to the - // offset maximum established for the open file - // descriptor associated with fildes. - case EISDIR: // An attempt is made to read a directory. - case ENOBUFS: // An attempt to allocate a memory buffer fails. - case ENOMEM: // Insufficient memory is available. - status = eConnectionStatusError; - break; // Break to close.... - - case ENOENT: // no such file or directory - case EBADF: // fildes is not a valid file or socket descriptor open for reading. - case ENXIO: // An action is requested of a device that does not exist.. - // A requested action cannot be performed by the device. - case ECONNRESET:// The connection is closed by the peer during a read attempt on a socket. - case ENOTCONN: // A read is attempted on an unconnected socket. - status = eConnectionStatusLostConnection; - break; // Break to close.... - - case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a socket. - status = eConnectionStatusTimedOut; - return 0; - - default: - if (log) - log->Printf("%p ConnectionFileDescriptor::Read (), unexpected error: %s", - static_cast(this), strerror(error_value)); - status = eConnectionStatusError; - break; // Break to close.... - - } - - return 0; - } - return bytes_read; -} - -size_t -ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf ("%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 ")", - static_cast(this), static_cast(src), - static_cast(src_len)); - - if (!IsConnected ()) - { - if (error_ptr) - error_ptr->SetErrorString("not connected"); - status = eConnectionStatusNoConnection; - return 0; - } - - - Error error; - - size_t bytes_sent = src_len; - error = m_write_sp->Write(src, bytes_sent); - - if (log) - { - log->Printf ("%p ConnectionFileDescriptor::Write(fd = %" PRIu64 ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 " (error = %s)", - static_cast(this), - static_cast(m_write_sp->GetWaitableHandle()), - static_cast(src), - static_cast(src_len), - static_cast(bytes_sent), - error.AsCString()); - } - - if (error_ptr) - *error_ptr = error; - - if (error.Fail()) - { - switch (error.GetError()) - { - case EAGAIN: - case EINTR: - status = eConnectionStatusSuccess; - return 0; - - case ECONNRESET:// The connection is closed by the peer during a read attempt on a socket. - case ENOTCONN: // A read is attempted on an unconnected socket. - status = eConnectionStatusLostConnection; - break; // Break to close.... - - default: - status = eConnectionStatusError; - break; // Break to close.... - } - - return 0; - } - - status = eConnectionStatusSuccess; - return bytes_sent; -} - - - -// This ConnectionFileDescriptor::BytesAvailable() uses select(). -// -// PROS: -// - select is consistent across most unix platforms -// - The Apple specific version allows for unlimited fds in the fd_sets by -// setting the _DARWIN_UNLIMITED_SELECT define prior to including the -// required header files. -// CONS: -// - on non-Apple platforms, only supports file descriptors up to FD_SETSIZE. -// This implementation will assert if it runs into that hard limit to let -// users know that another ConnectionFileDescriptor::BytesAvailable() should -// be used or a new version of ConnectionFileDescriptor::BytesAvailable() -// should be written for the system that is running into the limitations. - -#if defined(__APPLE__) -#define FD_SET_DATA(fds) fds.data() -#else -#define FD_SET_DATA(fds) &fds -#endif - -ConnectionStatus -ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_ptr) -{ - // Don't need to take the mutex here separately since we are only called from Read. If we - // ever get used more generally we will need to lock here as well. - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", - static_cast(this), timeout_usec); - - struct timeval *tv_ptr; - struct timeval tv; - if (timeout_usec == UINT32_MAX) - { - // Inifinite wait... - tv_ptr = nullptr; - } - else - { - TimeValue time_value; - time_value.OffsetWithMicroSeconds (timeout_usec); - tv.tv_sec = time_value.seconds(); - tv.tv_usec = time_value.microseconds(); - tv_ptr = &tv; - } - - // Make a copy of the file descriptors to make sure we don't - // have another thread change these values out from under us - // and cause problems in the loop below where like in FS_SET() - const IOObject::WaitableHandle handle = m_read_sp->GetWaitableHandle(); - const int pipe_fd = m_pipe.GetReadFileDescriptor(); - - if (handle != IOObject::kInvalidHandleValue) - { -#if defined(_MSC_VER) - // select() won't accept pipes on Windows. The entire Windows codepath needs to be - // converted over to using WaitForMultipleObjects and event HANDLEs, but for now at least - // this will allow ::select() to not return an error. - const bool have_pipe_fd = false; -#else - const bool have_pipe_fd = pipe_fd >= 0; -#if !defined(__APPLE__) - assert (handle < FD_SETSIZE); - if (have_pipe_fd) - assert (pipe_fd < FD_SETSIZE); -#endif -#endif - while (handle == m_read_sp->GetWaitableHandle()) - { - const int nfds = std::max(handle, pipe_fd) + 1; -#if defined(__APPLE__) - llvm::SmallVector read_fds; - read_fds.resize((nfds/FD_SETSIZE) + 1); - for (size_t i=0; iPrintf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i, %i}, NULL, NULL, timeout=%p)...", - static_cast(this), nfds, handle, pipe_fd, - static_cast(tv_ptr)); - else - log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p)...", - static_cast(this), nfds, handle, - static_cast(tv_ptr)); - } - - const int num_set_fds = ::select (nfds, FD_SET_DATA(read_fds), NULL, NULL, tv_ptr); - if (num_set_fds < 0) - error.SetErrorToErrno(); - else - error.Clear(); - - if (log) - { - if (have_pipe_fd) - log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i, %i}, NULL, NULL, timeout=%p) => %d, error = %s", - static_cast(this), nfds, handle, - pipe_fd, static_cast(tv_ptr), num_set_fds, - error.AsCString()); - else - log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p) => %d, error = %s", - static_cast(this), nfds, handle, - static_cast(tv_ptr), num_set_fds, - error.AsCString()); - } - - if (error_ptr) - *error_ptr = error; - - if (error.Fail()) - { - switch (error.GetError()) - { - case EBADF: // One of the descriptor sets specified an invalid descriptor. - return eConnectionStatusLostConnection; - - case EINVAL: // The specified time limit is invalid. One of its components is negative or too large. - default: // Other unknown error - return eConnectionStatusError; - - case EAGAIN: // The kernel was (perhaps temporarily) unable to - // allocate the requested number of file descriptors, - // or we have non-blocking IO - case EINTR: // A signal was delivered before the time limit - // expired and before any of the selected events - // occurred. - break; // Lets keep reading to until we timeout - } - } - else if (num_set_fds == 0) - { - return eConnectionStatusTimedOut; - } - else if (num_set_fds > 0) - { - if (FD_ISSET(handle, FD_SET_DATA(read_fds))) - return eConnectionStatusSuccess; - if (have_pipe_fd && FD_ISSET(pipe_fd, FD_SET_DATA(read_fds))) - { - // We got a command to exit. Read the data from that pipe: - char buffer[16]; - ssize_t bytes_read; - - do - { - bytes_read = ::read (pipe_fd, buffer, sizeof(buffer)); - } while (bytes_read < 0 && errno == EINTR); - - switch (buffer[0]) - { - case 'q': - if (log) - log->Printf("%p ConnectionFileDescriptor::BytesAvailable() got data: %*s from the command channel.", - static_cast(this), - static_cast(bytes_read), buffer); - return eConnectionStatusEndOfFile; - case 'i': - // Interrupt the current read - return eConnectionStatusInterrupted; - } - } - } - } - } - - if (error_ptr) - error_ptr->SetErrorString("not connected"); - return eConnectionStatusLostConnection; -} - -ConnectionStatus -ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *error_ptr) -{ - Socket* socket = nullptr; - Error error = Socket::UnixDomainAccept(socket_name, socket); - if (error_ptr) - *error_ptr = error; - m_write_sp.reset(socket); - m_read_sp = m_write_sp; - return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; -} - -ConnectionStatus -ConnectionFileDescriptor::NamedSocketConnect (const char *socket_name, Error *error_ptr) -{ - Socket* socket = nullptr; - Error error = Socket::UnixDomainConnect(socket_name, socket); - if (error_ptr) - *error_ptr = error; - m_write_sp.reset(socket); - m_read_sp = m_write_sp; - return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; -} - -ConnectionStatus -ConnectionFileDescriptor::SocketListen(const char *s, Error *error_ptr) -{ - m_port_predicate.SetValue(0, eBroadcastNever); - - Socket* socket = nullptr; - m_waiting_for_accept = true; - Error error = Socket::TcpListen(s, socket, &m_port_predicate); - if (error_ptr) - *error_ptr = error; - if (error.Fail()) - return eConnectionStatusError; - - std::unique_ptr listening_socket_up; - - listening_socket_up.reset(socket); - socket = nullptr; - error = listening_socket_up->BlockingAccept(s, socket); - listening_socket_up.reset(); - if (error_ptr) - *error_ptr = error; - if (error.Fail()) - return eConnectionStatusError; - - m_write_sp.reset(socket); - m_read_sp = m_write_sp; - return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; -} - -ConnectionStatus -ConnectionFileDescriptor::ConnectTCP(const char *s, Error *error_ptr) -{ - Socket* socket = nullptr; - Error error = Socket::TcpConnect(s, socket); - if (error_ptr) - *error_ptr = error; - m_write_sp.reset(socket); - m_read_sp = m_write_sp; - return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; -} - -ConnectionStatus -ConnectionFileDescriptor::ConnectUDP(const char *s, Error *error_ptr) -{ - Socket* send_socket = nullptr; - Socket* recv_socket = nullptr; - Error error = Socket::UdpConnect(s, send_socket, recv_socket); - if (error_ptr) - *error_ptr = error; - m_write_sp.reset(send_socket); - m_read_sp.reset(recv_socket); - return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; -} - - -uint16_t ConnectionFileDescriptor::GetListeningPort(uint32_t timeout_sec) -{ - uint16_t bound_port = 0; - if (timeout_sec == UINT32_MAX) - m_port_predicate.WaitForValueNotEqualTo (0, bound_port); - else - { - TimeValue timeout = TimeValue::Now(); - timeout.OffsetWithSeconds(timeout_sec); - m_port_predicate.WaitForValueNotEqualTo (0, bound_port, &timeout); - } - return bound_port; -} diff --git a/source/Core/ConnectionSharedMemory.cpp b/source/Core/ConnectionSharedMemory.cpp index 5db3d687cdb2..1cbee20cd94a 100644 --- a/source/Core/ConnectionSharedMemory.cpp +++ b/source/Core/ConnectionSharedMemory.cpp @@ -6,6 +6,7 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +#ifndef __ANDROID_NDK__ #include "lldb/Core/ConnectionSharedMemory.h" @@ -156,3 +157,4 @@ ConnectionSharedMemory::Open (bool create, const char *name, size_t size, Error return eConnectionStatusError; } +#endif // __ANDROID_NDK__ diff --git a/source/Core/ConstString.cpp b/source/Core/ConstString.cpp index 5657b483a495..37d24e0dec00 100644 --- a/source/Core/ConstString.cpp +++ b/source/Core/ConstString.cpp @@ -11,6 +11,8 @@ #include "lldb/Host/Mutex.h" #include "llvm/ADT/StringMap.h" +#include + using namespace lldb_private; @@ -93,7 +95,7 @@ public: { Mutex::Locker locker (m_mutex); llvm::StringRef string_ref (cstr, cstr_len); - StringPoolEntryType& entry = m_string_map.GetOrCreateValue (string_ref, (StringPoolValueType)NULL); + StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first; return entry.getKeyData(); } return NULL; @@ -105,7 +107,7 @@ public: if (string_ref.data()) { Mutex::Locker locker (m_mutex); - StringPoolEntryType& entry = m_string_map.GetOrCreateValue (string_ref, (StringPoolValueType)NULL); + StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first; return entry.getKeyData(); } return NULL; @@ -118,7 +120,7 @@ public: { Mutex::Locker locker (m_mutex); // Make string pool entry with the mangled counterpart already set - StringPoolEntryType& entry = m_string_map.GetOrCreateValue (llvm::StringRef (demangled_cstr), mangled_ccstr); + StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (llvm::StringRef (demangled_cstr), mangled_ccstr)).first; // Extract the const version of the demangled_cstr const char *demangled_ccstr = entry.getKeyData(); @@ -184,25 +186,16 @@ protected: // we can't guarantee that some objects won't get destroyed after the // global destructor chain is run, and trying to make sure no destructors // touch ConstStrings is difficult. So we leak the pool instead. -// -// FIXME: If we are going to keep it this way we should come up with some -// abstraction to "pthread_once" so we don't have to check the pointer -// every time. //---------------------------------------------------------------------- static Pool & StringPool() { - static Mutex g_pool_initialization_mutex; + static std::once_flag g_pool_initialization_flag; static Pool *g_string_pool = NULL; - if (g_string_pool == NULL) - { - Mutex::Locker initialization_locker(g_pool_initialization_mutex); - if (g_string_pool == NULL) - { - g_string_pool = new Pool(); - } - } + std::call_once(g_pool_initialization_flag, [] () { + g_string_pool = new Pool(); + }); return *g_string_pool; } diff --git a/source/Core/DataExtractor.cpp b/source/Core/DataExtractor.cpp index a0958bd6b1c6..6e1d63095cf3 100644 --- a/source/Core/DataExtractor.cpp +++ b/source/Core/DataExtractor.cpp @@ -22,7 +22,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/MathExtras.h" - +#include "llvm/Support/MD5.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" @@ -132,7 +132,8 @@ DataExtractor::DataExtractor () : m_end (NULL), m_byte_order(lldb::endian::InlHostByteOrder()), m_addr_size (4), - m_data_sp () + m_data_sp (), + m_target_byte_size(1) { } @@ -140,12 +141,13 @@ DataExtractor::DataExtractor () : // 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. //---------------------------------------------------------------------- -DataExtractor::DataExtractor (const void* data, offset_t length, ByteOrder endian, uint32_t addr_size) : +DataExtractor::DataExtractor (const void* data, offset_t length, ByteOrder endian, uint32_t addr_size, uint32_t target_byte_size/*=1*/) : m_start ((uint8_t*)data), m_end ((uint8_t*)data + length), m_byte_order(endian), m_addr_size (addr_size), - m_data_sp () + m_data_sp (), + m_target_byte_size(target_byte_size) { } @@ -156,12 +158,13 @@ DataExtractor::DataExtractor (const void* data, offset_t length, ByteOrder endia // as long as any DataExtractor objects exist that have a reference to // this data. //---------------------------------------------------------------------- -DataExtractor::DataExtractor (const DataBufferSP& data_sp, ByteOrder endian, uint32_t addr_size) : +DataExtractor::DataExtractor (const DataBufferSP& data_sp, ByteOrder endian, uint32_t addr_size, uint32_t target_byte_size/*=1*/) : m_start (NULL), m_end (NULL), m_byte_order(endian), m_addr_size (addr_size), - m_data_sp () + m_data_sp (), + m_target_byte_size(target_byte_size) { SetData (data_sp); } @@ -173,12 +176,13 @@ DataExtractor::DataExtractor (const DataBufferSP& data_sp, ByteOrder endian, uin // as any object contains a reference to that data. The endian // swap and address size settings are copied from "data". //---------------------------------------------------------------------- -DataExtractor::DataExtractor (const DataExtractor& data, offset_t offset, offset_t length) : +DataExtractor::DataExtractor (const DataExtractor& data, offset_t offset, offset_t length, uint32_t target_byte_size/*=1*/) : m_start(NULL), m_end(NULL), m_byte_order(data.m_byte_order), m_addr_size(data.m_addr_size), - m_data_sp() + m_data_sp(), + m_target_byte_size(target_byte_size) { if (data.ValidOffset(offset)) { @@ -194,7 +198,8 @@ DataExtractor::DataExtractor (const DataExtractor& rhs) : m_end (rhs.m_end), m_byte_order (rhs.m_byte_order), m_addr_size (rhs.m_addr_size), - m_data_sp (rhs.m_data_sp) + m_data_sp (rhs.m_data_sp), + m_target_byte_size(rhs.m_target_byte_size) { } @@ -1480,7 +1485,9 @@ DataExtractor::Dump (Stream *s, s->EOL(); } if (base_addr != LLDB_INVALID_ADDRESS) - s->Printf ("0x%8.8" PRIx64 ": ", (uint64_t)(base_addr + (offset - start_offset))); + s->Printf ("0x%8.8" PRIx64 ": ", + (uint64_t)(base_addr + (offset - start_offset)/m_target_byte_size )); + line_start_offset = offset; } else @@ -1535,6 +1542,7 @@ DataExtractor::Dump (Stream *s, { s->Printf ("%2.2x", GetU8(&offset)); } + // Put an extra space between the groups of bytes if more than one // is being dumped in a group (item_byte_size is more than 1). if (item_byte_size > 1) @@ -2230,3 +2238,27 @@ DataExtractor::Append(void* buf, offset_t length) return true; } + +void +DataExtractor::Checksum (llvm::SmallVectorImpl &dest, + uint64_t max_data) +{ + if (max_data == 0) + max_data = GetByteSize(); + else + max_data = std::min(max_data, GetByteSize()); + + llvm::MD5 md5; + + const llvm::ArrayRef data(GetDataStart(),max_data); + md5.update(data); + + llvm::MD5::MD5Result result; + md5.final(result); + + dest.resize(16); + std::copy(result, + result+16, + dest.begin()); +} + diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp index 178296347677..c7342ade6cad 100644 --- a/source/Core/Debugger.cpp +++ b/source/Core/Debugger.cpp @@ -18,7 +18,6 @@ #include "llvm/ADT/StringRef.h" #include "lldb/lldb-private.h" -#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/RegisterValue.h" @@ -34,8 +33,10 @@ #include "lldb/DataFormatters/DataVisualization.h" #include "lldb/DataFormatters/FormatManager.h" #include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/Terminal.h" +#include "lldb/Host/ThreadLauncher.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/OptionValueSInt64.h" #include "lldb/Interpreter/OptionValueString.h" @@ -44,6 +45,8 @@ #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/Target/CPPLanguageRuntime.h" +#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/TargetList.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -61,6 +64,7 @@ using namespace lldb_private; static uint32_t g_shared_debugger_refcount = 0; static lldb::user_id_t g_unique_id = 1; +static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024; #pragma mark Static Functions @@ -121,12 +125,13 @@ g_language_enumerators[] = FILE_AND_LINE\ "\\n" - +#define DEFAULT_DISASSEMBLY_FORMAT "${current-pc-arrow}${addr-file-or-load}{ <${function.name-without-args}${function.concrete-only-addr-offset-no-padding}>}: " static PropertyDefinition g_properties[] = { { "auto-confirm", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." }, +{ "disassembly-format", OptionValue::eTypeString , true, 0 , DEFAULT_DISASSEMBLY_FORMAT, NULL, "The default disassembly format string to use when disassembling instruction sequences." }, { "frame-format", OptionValue::eTypeString , true, 0 , DEFAULT_FRAME_FORMAT, NULL, "The default frame format string to use when displaying stack frame information for threads." }, { "notify-void", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." }, { "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." }, @@ -139,7 +144,8 @@ g_properties[] = { "thread-format", OptionValue::eTypeString , true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." }, { "use-external-editor", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Whether to use an external editor or not." }, { "use-color", OptionValue::eTypeBoolean, true, true , NULL, NULL, "Whether to use Ansi color codes or not." }, -{ "auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." }, +{ "auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." }, +{ "escape-non-printables", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will automatically escape non-printable and escape characters when formatting strings." }, { NULL, OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL } }; @@ -147,6 +153,7 @@ g_properties[] = enum { ePropertyAutoConfirm = 0, + ePropertyDisassemblyFormat, ePropertyFrameFormat, ePropertyNotiftVoid, ePropertyPrompt, @@ -159,7 +166,8 @@ enum ePropertyThreadFormat, ePropertyUseExternalEditor, ePropertyUseColor, - ePropertyAutoOneLineSummaries + ePropertyAutoOneLineSummaries, + ePropertyEscapeNonPrintables }; Debugger::LoadPluginCallbackType Debugger::g_load_plugin_callback = NULL; @@ -171,6 +179,7 @@ Debugger::SetPropertyValue (const ExecutionContext *exe_ctx, const char *value) { bool is_load_script = strcmp(property_path,"target.load-script-from-symbol-file") == 0; + bool is_escape_non_printables = strcmp(property_path, "escape-non-printables") == 0; TargetSP target_sp; LoadScriptFromSymFile load_script_old_value; if (is_load_script && exe_ctx->GetTargetSP()) @@ -218,6 +227,10 @@ Debugger::SetPropertyValue (const ExecutionContext *exe_ctx, } } } + else if (is_escape_non_printables) + { + DataVisualization::ForceUpdate(); + } } return error; } @@ -229,6 +242,13 @@ Debugger::GetAutoConfirm () const return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); } +const char * +Debugger::GetDisassemblyFormat() const +{ + const uint32_t idx = ePropertyDisassemblyFormat; + return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); +} + const char * Debugger::GetFrameFormat() const { @@ -353,7 +373,13 @@ Debugger::GetAutoOneLineSummaries () const { const uint32_t idx = ePropertyAutoOneLineSummaries; return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true); +} +bool +Debugger::GetEscapeNonPrintables () const +{ + const uint32_t idx = ePropertyEscapeNonPrintables; + return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true); } #pragma mark Debugger @@ -620,24 +646,25 @@ Debugger::FindTargetWithProcess (Process *process) return target_sp; } -Debugger::Debugger (lldb::LogOutputCallback log_callback, void *baton) : - UserID (g_unique_id++), - Properties(OptionValuePropertiesSP(new OptionValueProperties())), - m_input_file_sp (new StreamFile (stdin, false)), - m_output_file_sp (new StreamFile (stdout, false)), - m_error_file_sp (new StreamFile (stderr, false)), - m_terminal_state (), - m_target_list (*this), - m_platform_list (), - m_listener ("lldb.Debugger"), +Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) : + UserID(g_unique_id++), + Properties(OptionValuePropertiesSP(new OptionValueProperties())), + m_input_file_sp(new StreamFile(stdin, false)), + m_output_file_sp(new StreamFile(stdout, false)), + m_error_file_sp(new StreamFile(stderr, false)), + m_terminal_state(), + m_target_list(*this), + m_platform_list(), + m_listener("lldb.Debugger"), m_source_manager_ap(), m_source_file_cache(), - m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)), - m_input_reader_stack (), - m_instance_name (), - m_loaded_plugins (), - m_event_handler_thread (LLDB_INVALID_HOST_THREAD), - m_io_handler_thread (LLDB_INVALID_HOST_THREAD) + m_command_interpreter_ap(new CommandInterpreter(*this, eScriptLanguageDefault, false)), + m_input_reader_stack(), + m_instance_name(), + m_loaded_plugins(), + m_event_handler_thread (), + m_io_handler_thread (), + m_sync_broadcaster (NULL, "lldb.debugger.sync") { char instance_cstr[256]; snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID()); @@ -646,7 +673,7 @@ Debugger::Debugger (lldb::LogOutputCallback log_callback, void *baton) : m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); m_command_interpreter_ap->Initialize (); // Always add our default platform to the platform list - PlatformSP default_platform_sp (Platform::GetDefaultPlatform()); + PlatformSP default_platform_sp (Platform::GetHostPlatform()); assert (default_platform_sp.get()); m_platform_list.Append (default_platform_sp, true); @@ -903,7 +930,6 @@ Debugger::GetTopIOHandlerControlSequence(char ch) void Debugger::RunIOHandler (const IOHandlerSP& reader_sp) { - Mutex::Locker locker (m_input_reader_stack.GetMutex()); PushIOHandler (reader_sp); IOHandlerSP top_reader_sp = reader_sp; @@ -1129,6 +1155,8 @@ TestPromptFormats (StackFrame *frame) StreamString s; const char *prompt_format = "{addr = '${addr}'\n}" + "{addr-file-or-load = '${addr-file-or-load}'\n}" + "{current-pc-arrow = '${current-pc-arrow}'\n}" "{process.id = '${process.id}'\n}" "{process.name = '${process.name}'\n}" "{process.file.basename = '${process.file.basename}'\n}" @@ -1156,9 +1184,13 @@ TestPromptFormats (StackFrame *frame) "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}" "{frame.reg.carp = '${frame.reg.carp}'\n}" "{function.id = '${function.id}'\n}" + "{function.changed = '${function.changed}'\n}" + "{function.initial-function = '${function.initial-function}'\n}" "{function.name = '${function.name}'\n}" + "{function.name-without-args = '${function.name-without-args}'\n}" "{function.name-with-args = '${function.name-with-args}'\n}" "{function.addr-offset = '${function.addr-offset}'\n}" + "{function.concrete-only-addr-offset-no-padding = '${function.concrete-only-addr-offset-no-padding}'\n}" "{function.line-offset = '${function.line-offset}'\n}" "{function.pc-offset = '${function.pc-offset}'\n}" "{line.file.basename = '${line.file.basename}'\n}" @@ -1556,7 +1588,9 @@ FormatPromptRecurse const Address *addr, Stream &s, const char **end, - ValueObject* valobj + ValueObject* valobj, + bool function_changed, + bool initial_function ) { ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers @@ -1598,7 +1632,7 @@ FormatPromptRecurse ++p; // Skip the '{' - if (FormatPromptRecurse (p, sc, exe_ctx, addr, sub_strm, &p, valobj)) + if (FormatPromptRecurse (p, sc, exe_ctx, addr, sub_strm, &p, valobj, function_changed, initial_function)) { // The stream had all it needed s.Write(sub_strm.GetData(), sub_strm.GetSize()); @@ -1632,6 +1666,12 @@ FormatPromptRecurse const char *cstr = NULL; std::string token_format; Address format_addr; + + // normally "addr" means print a raw address but + // "file-addr-or-load-addr" means print a module + file addr if there's no load addr + bool print_file_addr_or_load_addr = false; + bool addr_offset_concrete_func_only = false; + bool addr_offset_print_with_no_padding = false; bool calculate_format_addr_function_offset = false; // Set reg_kind and reg_num to invalid values RegisterKind reg_kind = kNumRegisterKinds; @@ -1710,6 +1750,15 @@ FormatPromptRecurse target = valobj; val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; } + else if (IsToken (var_name_begin, "var.script:")) + { + var_name_begin += ::strlen("var.script:"); + std::string script_name(var_name_begin,var_name_end); + ScriptInterpreter* script_interpreter = valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + if (RunScriptFormatKeyword (s, script_interpreter, valobj, script_name)) + var_success = true; + break; + } else if (IsToken (var_name_begin,"var%")) { was_var_format = true; @@ -1778,6 +1827,7 @@ FormatPromptRecurse log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d," " final_value_type %d", first_unparsed, reason_to_stop, final_value_type); + target = target->GetQualifiedRepresentationIfAvailable(target->GetDynamicValueType(), true).get(); } } else @@ -1826,8 +1876,8 @@ FormatPromptRecurse // TODO use flags for these const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL); - bool is_array = (type_info_flags & ClangASTType::eTypeIsArray) != 0; - bool is_pointer = (type_info_flags & ClangASTType::eTypeIsPointer) != 0; + bool is_array = (type_info_flags & eTypeIsArray) != 0; + bool is_pointer = (type_info_flags & eTypeIsPointer) != 0; bool is_aggregate = target->GetClangType().IsAggregateType(); if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions @@ -1942,7 +1992,7 @@ FormatPromptRecurse if (!special_directions) var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); else - var_success &= FormatPromptRecurse(special_directions, sc, exe_ctx, addr, s, NULL, item); + var_success &= FormatPromptRecurse(special_directions, sc, exe_ctx, addr, s, NULL, item, function_changed, initial_function); if (--max_num_children == 0) { @@ -1958,7 +2008,12 @@ FormatPromptRecurse } break; case 'a': - if (IsToken (var_name_begin, "addr}")) + if (IsToken (var_name_begin, "addr-file-or-load}")) + { + print_file_addr_or_load_addr = true; + } + if (IsToken (var_name_begin, "addr}") + || IsToken (var_name_begin, "addr-file-or-load}")) { if (addr && addr->IsValid()) { @@ -2160,8 +2215,7 @@ FormatPromptRecurse } } break; - - + case 'm': if (IsToken (var_name_begin, "module.")) { @@ -2289,6 +2343,14 @@ FormatPromptRecurse var_success = true; } + if (IsToken (var_name_begin, "changed}") && function_changed) + { + var_success = true; + } + if (IsToken (var_name_begin, "initial-function}") && initial_function) + { + var_success = true; + } else if (IsToken (var_name_begin, "name}")) { if (sc->function) @@ -2315,6 +2377,19 @@ FormatPromptRecurse var_success = true; } } + else if (IsToken (var_name_begin, "name-without-args}")) + { + ConstString name; + if (sc->function) + name = sc->function->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); + else if (sc->symbol) + name = sc->symbol->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); + if (name) + { + s.PutCString(name.GetCString()); + var_success = true; + } + } else if (IsToken (var_name_begin, "name-with-args}")) { // Print the function name with arguments in it @@ -2418,7 +2493,7 @@ FormatPromptRecurse .SetHideItemNames(false) .SetShowMembersOneLiner(true), ""); - format.FormatObject(var_value_sp.get(), buffer); + format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions()); var_representation = buffer.c_str(); } else @@ -2458,8 +2533,14 @@ FormatPromptRecurse } } } - else if (IsToken (var_name_begin, "addr-offset}")) + else if (IsToken (var_name_begin, "addr-offset}") + || IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}")) { + if (IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}")) + { + addr_offset_print_with_no_padding = true; + addr_offset_concrete_func_only = true; + } var_success = addr != NULL; if (var_success) { @@ -2530,6 +2611,35 @@ FormatPromptRecurse } } break; + case 'c': + if (IsToken (var_name_begin, "current-pc-arrow")) + { + if (addr && exe_ctx && exe_ctx->GetFramePtr()) + { + RegisterContextSP reg_ctx = exe_ctx->GetFramePtr()->GetRegisterContextSP(); + if (reg_ctx.get()) + { + addr_t pc_loadaddr = reg_ctx->GetPC(); + if (pc_loadaddr != LLDB_INVALID_ADDRESS) + { + Address pc; + pc.SetLoadAddress (pc_loadaddr, exe_ctx->GetTargetPtr()); + if (pc == *addr) + { + s.Printf ("-> "); + var_success = true; + } + } + } + if (var_success == false) + { + s.Printf(" "); + var_success = true; + } + } + var_success = true; + } + break; } if (var_success) @@ -2587,7 +2697,7 @@ FormatPromptRecurse if (sc->function) { func_addr = sc->function->GetAddressRange().GetBaseAddress(); - if (sc->block) + if (sc->block && addr_offset_concrete_func_only == false) { // Check to make sure we aren't in an inline // function. If we are, use the inline block @@ -2605,14 +2715,19 @@ FormatPromptRecurse if (func_addr.IsValid()) { + const char *addr_offset_padding = " "; + if (addr_offset_print_with_no_padding) + { + addr_offset_padding = ""; + } if (func_addr.GetSection() == format_addr.GetSection()) { addr_t func_file_addr = func_addr.GetFileAddress(); addr_t addr_file_addr = format_addr.GetFileAddress(); if (addr_file_addr > func_file_addr) - s.Printf(" + %" PRIu64, addr_file_addr - func_file_addr); + s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_file_addr - func_file_addr); else if (addr_file_addr < func_file_addr) - s.Printf(" - %" PRIu64, func_file_addr - addr_file_addr); + s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_file_addr - addr_file_addr); var_success = true; } else @@ -2623,9 +2738,9 @@ FormatPromptRecurse addr_t func_load_addr = func_addr.GetLoadAddress (target); addr_t addr_load_addr = format_addr.GetLoadAddress (target); if (addr_load_addr > func_load_addr) - s.Printf(" + %" PRIu64, addr_load_addr - func_load_addr); + s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_load_addr - func_load_addr); else if (addr_load_addr < func_load_addr) - s.Printf(" - %" PRIu64, func_load_addr - addr_load_addr); + s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_load_addr - addr_load_addr); var_success = true; } } @@ -2642,10 +2757,21 @@ FormatPromptRecurse if (vaddr != LLDB_INVALID_ADDRESS) { - int addr_width = target->GetArchitecture().GetAddressByteSize() * 2; + int addr_width = 0; + if (exe_ctx && target) + { + addr_width = target->GetArchitecture().GetAddressByteSize() * 2; + } if (addr_width == 0) addr_width = 16; - s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); + if (print_file_addr_or_load_addr) + { + format_addr.Dump (&s, exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0); + } + else + { + s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); + } var_success = true; } } @@ -2759,9 +2885,55 @@ Debugger::FormatPrompt std::string format_str = lldb_utility::ansi::FormatAnsiTerminalCodes (format, use_color); if (format_str.length()) format = format_str.c_str(); - return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, valobj); + return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, valobj, false, false); +} + +bool +Debugger::FormatDisassemblerAddress (const char *format, + const SymbolContext *sc, + const SymbolContext *prev_sc, + const ExecutionContext *exe_ctx, + const Address *addr, + Stream &s) +{ + if (format == NULL && exe_ctx != NULL && exe_ctx->HasTargetScope()) + { + format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); + } + bool function_changed = false; + bool initial_function = false; + if (prev_sc && (prev_sc->function || prev_sc->symbol)) + { + if (sc && (sc->function || sc->symbol)) + { + if (prev_sc->symbol && sc->symbol) + { + if (!sc->symbol->Compare (prev_sc->symbol->GetName(), prev_sc->symbol->GetType())) + { + function_changed = true; + } + } + else if (prev_sc->function && sc->function) + { + if (prev_sc->function->GetMangled() != sc->function->GetMangled()) + { + function_changed = true; + } + } + } + } + // The first context on a list of instructions will have a prev_sc that + // has no Function or Symbol -- if SymbolContext had an IsValid() method, it + // would return false. But we do get a prev_sc pointer. + if ((sc && (sc->function || sc->symbol)) + && prev_sc && (prev_sc->function == NULL && prev_sc->symbol == NULL)) + { + initial_function = true; + } + return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, NULL, function_changed, initial_function); } + void Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton) { @@ -2952,6 +3124,7 @@ Debugger::GetProcessSTDERR (Process *process, Stream *stream) return total_bytes; } + // This function handles events that were broadcast by the process. void Debugger::HandleProcessEvent (const EventSP &event_sp) @@ -2959,7 +3132,7 @@ Debugger::HandleProcessEvent (const EventSP &event_sp) using namespace lldb; const uint32_t event_type = event_sp->GetType(); ProcessSP process_sp = Process::ProcessEventData::GetProcessFromEvent(event_sp.get()); - + StreamString output_stream; StreamString error_stream; const bool gui_enabled = IsForwardingEvents(); @@ -2968,191 +3141,27 @@ Debugger::HandleProcessEvent (const EventSP &event_sp) { bool pop_process_io_handler = false; assert (process_sp); - + if (event_type & Process::eBroadcastBitSTDOUT || event_type & Process::eBroadcastBitStateChanged) { GetProcessSTDOUT (process_sp.get(), &output_stream); } - + if (event_type & Process::eBroadcastBitSTDERR || event_type & Process::eBroadcastBitStateChanged) { GetProcessSTDERR (process_sp.get(), &error_stream); } - + if (event_type & Process::eBroadcastBitStateChanged) { - - // Drain all stout and stderr so we don't see any output come after - // we print our prompts - // Something changed in the process; get the event and report the process's current status and location to - // the user. - StateType event_state = Process::ProcessEventData::GetStateFromEvent (event_sp.get()); - if (event_state == eStateInvalid) - return; - - switch (event_state) - { - case eStateInvalid: - case eStateUnloaded: - case eStateConnected: - case eStateAttaching: - case eStateLaunching: - case eStateStepping: - case eStateDetached: - { - output_stream.Printf("Process %" PRIu64 " %s\n", - process_sp->GetID(), - StateAsCString (event_state)); - - if (event_state == eStateDetached) - pop_process_io_handler = true; - } - break; - - case eStateRunning: - // Don't be chatty when we run... - break; - - case eStateExited: - process_sp->GetStatus(output_stream); - pop_process_io_handler = true; - break; - - case eStateStopped: - case eStateCrashed: - case eStateSuspended: - // Make sure the program hasn't been auto-restarted: - if (Process::ProcessEventData::GetRestartedFromEvent (event_sp.get())) - { - size_t num_reasons = Process::ProcessEventData::GetNumRestartedReasons(event_sp.get()); - if (num_reasons > 0) - { - // FIXME: Do we want to report this, or would that just be annoyingly chatty? - if (num_reasons == 1) - { - const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), 0); - output_stream.Printf("Process %" PRIu64 " stopped and restarted: %s\n", - process_sp->GetID(), - reason ? reason : ""); - } - else - { - output_stream.Printf("Process %" PRIu64 " stopped and restarted, reasons:\n", - process_sp->GetID()); - - - for (size_t i = 0; i < num_reasons; i++) - { - const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), i); - output_stream.Printf("\t%s\n", reason ? reason : ""); - } - } - } - } - else - { - // Lock the thread list so it doesn't change on us, this is the scope for the locker: - { - ThreadList &thread_list = process_sp->GetThreadList(); - Mutex::Locker locker (thread_list.GetMutex()); - - ThreadSP curr_thread (thread_list.GetSelectedThread()); - ThreadSP thread; - StopReason curr_thread_stop_reason = eStopReasonInvalid; - if (curr_thread) - curr_thread_stop_reason = curr_thread->GetStopReason(); - if (!curr_thread || - !curr_thread->IsValid() || - curr_thread_stop_reason == eStopReasonInvalid || - curr_thread_stop_reason == eStopReasonNone) - { - // Prefer a thread that has just completed its plan over another thread as current thread. - ThreadSP plan_thread; - ThreadSP other_thread; - const size_t num_threads = thread_list.GetSize(); - size_t i; - for (i = 0; i < num_threads; ++i) - { - thread = thread_list.GetThreadAtIndex(i); - StopReason thread_stop_reason = thread->GetStopReason(); - switch (thread_stop_reason) - { - case eStopReasonInvalid: - case eStopReasonNone: - break; - - case eStopReasonTrace: - case eStopReasonBreakpoint: - case eStopReasonWatchpoint: - case eStopReasonSignal: - case eStopReasonException: - case eStopReasonExec: - case eStopReasonThreadExiting: - if (!other_thread) - other_thread = thread; - break; - case eStopReasonPlanComplete: - if (!plan_thread) - plan_thread = thread; - break; - } - } - if (plan_thread) - thread_list.SetSelectedThreadByID (plan_thread->GetID()); - else if (other_thread) - thread_list.SetSelectedThreadByID (other_thread->GetID()); - else - { - if (curr_thread && curr_thread->IsValid()) - thread = curr_thread; - else - thread = thread_list.GetThreadAtIndex(0); - - if (thread) - thread_list.SetSelectedThreadByID (thread->GetID()); - } - } - } - // Drop the ThreadList mutex by here, since GetThreadStatus below might have to run code, - // e.g. for Data formatters, and if we hold the ThreadList mutex, then the process is going to - // have a hard time restarting the process. - - if (GetTargetList().GetSelectedTarget().get() == &process_sp->GetTarget()) - { - const bool only_threads_with_stop_reason = true; - const uint32_t start_frame = 0; - const uint32_t num_frames = 1; - const uint32_t num_frames_with_source = 1; - process_sp->GetStatus(output_stream); - process_sp->GetThreadStatus (output_stream, - only_threads_with_stop_reason, - start_frame, - num_frames, - num_frames_with_source); - } - else - { - uint32_t target_idx = GetTargetList().GetIndexOfTarget(process_sp->GetTarget().shared_from_this()); - if (target_idx != UINT32_MAX) - output_stream.Printf ("Target %d: (", target_idx); - else - output_stream.Printf ("Target : ("); - process_sp->GetTarget().Dump (&output_stream, eDescriptionLevelBrief); - output_stream.Printf (") stopped.\n"); - } - - // Pop the process IO handler - pop_process_io_handler = true; - } - break; - } + Process::HandleProcessStateChangedEvent (event_sp, &output_stream, pop_process_io_handler); } - + if (output_stream.GetSize() || error_stream.GetSize()) { StreamFileSP error_stream_sp (GetOutputFile()); bool top_io_handler_hid = false; - + if (process_sp->ProcessIOHandlerIsActive() == false) top_io_handler_hid = HideTopIOHandler(); @@ -3245,17 +3254,14 @@ Debugger::DefaultEventHandler() CommandInterpreter::eBroadcastBitQuitCommandReceived | CommandInterpreter::eBroadcastBitAsynchronousOutputData | CommandInterpreter::eBroadcastBitAsynchronousErrorData ); - + + // Let the thread that spawned us know that we have started up and + // that we are now listening to all required events so no events get missed + m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening); + bool done = false; while (!done) { -// Mutex::Locker locker; -// if (locker.TryLock(m_input_reader_stack.GetMutex())) -// { -// if (m_input_reader_stack.IsEmpty()) -// break; -// } -// EventSP event_sp; if (listener.WaitForEvent(NULL, event_sp)) { @@ -3337,19 +3343,38 @@ Debugger::EventHandlerThread (lldb::thread_arg_t arg) bool Debugger::StartEventHandlerThread() { - if (!IS_VALID_LLDB_HOST_THREAD(m_event_handler_thread)) - m_event_handler_thread = Host::ThreadCreate("lldb.debugger.event-handler", EventHandlerThread, this, NULL); - return IS_VALID_LLDB_HOST_THREAD(m_event_handler_thread); + if (!m_event_handler_thread.IsJoinable()) + { + // We must synchronize with the DefaultEventHandler() thread to ensure + // it is up and running and listening to events before we return from + // this function. We do this by listening to events for the + // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster + Listener listener("lldb.debugger.event-handler"); + listener.StartListeningForEvents(&m_sync_broadcaster, eBroadcastBitEventThreadIsListening); + + // Use larger 8MB stack for this thread + m_event_handler_thread = ThreadLauncher::LaunchThread("lldb.debugger.event-handler", EventHandlerThread, + this, + NULL, + g_debugger_event_thread_stack_bytes); + + // Make sure DefaultEventHandler() is running and listening to events before we return + // from this function. We are only listening for events of type + // eBroadcastBitEventThreadIsListening so we don't need to check the event, we just need + // to wait an infinite amount of time for it (NULL timeout as the first parameter) + lldb::EventSP event_sp; + listener.WaitForEvent(NULL, event_sp); + } + return m_event_handler_thread.IsJoinable(); } void Debugger::StopEventHandlerThread() { - if (IS_VALID_LLDB_HOST_THREAD(m_event_handler_thread)) + if (m_event_handler_thread.IsJoinable()) { GetCommandInterpreter().BroadcastEvent(CommandInterpreter::eBroadcastBitQuitCommandReceived); - Host::ThreadJoin(m_event_handler_thread, NULL, NULL); - m_event_handler_thread = LLDB_INVALID_HOST_THREAD; + m_event_handler_thread.Join(nullptr); } } @@ -3366,21 +3391,43 @@ Debugger::IOHandlerThread (lldb::thread_arg_t arg) bool Debugger::StartIOHandlerThread() { - if (!IS_VALID_LLDB_HOST_THREAD(m_io_handler_thread)) - m_io_handler_thread = Host::ThreadCreate("lldb.debugger.io-handler", IOHandlerThread, this, NULL); - return IS_VALID_LLDB_HOST_THREAD(m_io_handler_thread); + if (!m_io_handler_thread.IsJoinable()) + m_io_handler_thread = ThreadLauncher::LaunchThread ("lldb.debugger.io-handler", + IOHandlerThread, + this, + NULL, + 8*1024*1024); // Use larger 8MB stack for this thread + return m_io_handler_thread.IsJoinable(); } void Debugger::StopIOHandlerThread() { - if (IS_VALID_LLDB_HOST_THREAD(m_io_handler_thread)) + if (m_io_handler_thread.IsJoinable()) { if (m_input_file_sp) m_input_file_sp->GetFile().Close(); - Host::ThreadJoin(m_io_handler_thread, NULL, NULL); - m_io_handler_thread = LLDB_INVALID_HOST_THREAD; + m_io_handler_thread.Join(nullptr); } } +Target * +Debugger::GetDummyTarget() +{ + return m_target_list.GetDummyTarget (*this).get(); +} + +Target * +Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) +{ + Target *target = nullptr; + if (!prefer_dummy) + { + target = m_target_list.GetSelectedTarget().get(); + if (target) + return target; + } + + return GetDummyTarget(); +} diff --git a/source/Core/Disassembler.cpp b/source/Core/Disassembler.cpp index 1d2b8cf04c32..649f0c5bcb26 100644 --- a/source/Core/Disassembler.cpp +++ b/source/Core/Disassembler.cpp @@ -410,17 +410,18 @@ Disassembler::PrintInstructions SymbolContext prev_sc; AddressRange sc_range; const Address *pc_addr_ptr = NULL; - ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope(); StackFrame *frame = exe_ctx.GetFramePtr(); TargetSP target_sp (exe_ctx.GetTargetSP()); SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); if (frame) + { pc_addr_ptr = &frame->GetFrameCodeAddress(); + } const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = false; - for (size_t i=0; iGetInstructionList().GetInstructionAtIndex (i).get(); if (inst) @@ -447,7 +448,7 @@ Disassembler::PrintInstructions if (offset != 0) strm.EOL(); - sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false); + sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false, false); strm.EOL(); if (sc.comp_unit && sc.line_entry.IsValid()) @@ -462,23 +463,6 @@ Disassembler::PrintInstructions } } } - else if ((sc.function || sc.symbol) && (sc.function != prev_sc.function || sc.symbol != prev_sc.symbol)) - { - if (prev_sc.function || prev_sc.symbol) - strm.EOL(); - - bool show_fullpaths = false; - bool show_module = true; - bool show_inlined_frames = true; - sc.DumpStopContext (&strm, - exe_scope, - addr, - show_fullpaths, - show_module, - show_inlined_frames); - - strm << ":\n"; - } } else { @@ -486,12 +470,13 @@ Disassembler::PrintInstructions } } - if ((options & eOptionMarkPCAddress) && pc_addr_ptr) + const bool show_bytes = (options & eOptionShowBytes) != 0; + const char *disassembly_format = "${addr-file-or-load}: "; + if (exe_ctx.HasTargetScope()) { - strm.PutCString(inst_is_at_pc ? "-> " : " "); + disassembly_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat (); } - const bool show_bytes = (options & eOptionShowBytes) != 0; - inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx); + inst->Dump (&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, &prev_sc, disassembly_format); strm.EOL(); } else @@ -578,7 +563,10 @@ Instruction::Dump (lldb_private::Stream *s, uint32_t max_opcode_byte_size, bool show_address, bool show_bytes, - const ExecutionContext* exe_ctx) + const ExecutionContext* exe_ctx, + const SymbolContext *sym_ctx, + const SymbolContext *prev_sym_ctx, + const char *disassembly_addr_format_spec) { size_t opcode_column_width = 7; const size_t operand_column_width = 25; @@ -589,13 +577,7 @@ Instruction::Dump (lldb_private::Stream *s, if (show_address) { - m_address.Dump(&ss, - exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL, - Address::DumpStyleLoadAddress, - Address::DumpStyleModuleWithFileAddress, - 0); - - ss.PutCString(": "); + Debugger::FormatDisassemblerAddress (disassembly_addr_format_spec, sym_ctx, prev_sym_ctx, exe_ctx, &m_address, ss); } if (show_bytes) @@ -621,7 +603,7 @@ Instruction::Dump (lldb_private::Stream *s, } } - const size_t opcode_pos = ss.GetSize(); + const size_t opcode_pos = ss.GetSizeOfLastLine(); // The default opcode size of 7 characters is plenty for most architectures // but some like arm can pull out the occasional vqrshrun.s16. We won't get @@ -1003,13 +985,18 @@ InstructionList::Dump (Stream *s, { const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize(); collection::const_iterator pos, begin, end; + const char *disassemble_format = "${addr-file-or-load}: "; + if (exe_ctx) + { + disassemble_format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat (); + } for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin; pos != end; ++pos) { if (pos != begin) s->EOL(); - (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx); + (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx, NULL, NULL, disassemble_format); } } diff --git a/source/Core/FastDemangle.cpp b/source/Core/FastDemangle.cpp index 00a75425b689..53e8972e8048 100644 --- a/source/Core/FastDemangle.cpp +++ b/source/Core/FastDemangle.cpp @@ -18,7 +18,7 @@ //#define DEBUG_REORDERING 1 namespace { - + /// @brief Represents the collection of qualifiers on a type enum Qualifiers @@ -51,7 +51,7 @@ enum class OperatorKind struct Operator { - const char * name; + const char *name; OperatorKind kind; }; @@ -87,28 +87,28 @@ struct NameState class SymbolDemangler { public: - + //---------------------------------------------------- // Public API //---------------------------------------------------- - + /// @brief Create a SymbolDemangler /// /// The newly created demangler allocates and owns scratch memory sufficient /// for demangling typical symbols. Additional memory will be allocated if /// needed and managed by the demangler instance. - + SymbolDemangler() { - buffer = (char *) malloc(8192); - buffer_end = buffer + 8192; - owns_buffer = true; - - rewrite_ranges = (BufferRange *) malloc(128 * sizeof(BufferRange)); - rewrite_ranges_size = 128; - owns_rewrite_ranges = true; + m_buffer = (char *) malloc(8192); + m_buffer_end = m_buffer + 8192; + m_owns_buffer = true; + + m_rewrite_ranges = (BufferRange *) malloc(128 * sizeof (BufferRange)); + m_rewrite_ranges_size = 128; + m_owns_m_rewrite_ranges = true; } - + /// @brief Create a SymbolDemangler that uses provided scratch memory /// /// The provided memory is not owned by the demangler. It will be @@ -124,34 +124,36 @@ public: /// /// @param storage_size Number of bytes of space available scratch memory /// referenced by storage_ptr - - SymbolDemangler(void * storage_ptr, int storage_size) + + SymbolDemangler(void *storage_ptr, int storage_size) { // Use up to 1/8th of the provided space for rewrite ranges - rewrite_ranges_size = (storage_size >> 3) / sizeof(BufferRange); - rewrite_ranges = (BufferRange *) storage_ptr; - owns_rewrite_ranges = false; - + m_rewrite_ranges_size = (storage_size >> 3) / sizeof (BufferRange); + m_rewrite_ranges = (BufferRange *) storage_ptr; + m_owns_m_rewrite_ranges = false; + // Use the rest for the character buffer - buffer = (char *) storage_ptr + rewrite_ranges_size * sizeof(BufferRange); - buffer_end = (const char *)storage_ptr + storage_size; - owns_buffer = false; + m_buffer = (char *) storage_ptr + m_rewrite_ranges_size * sizeof (BufferRange); + m_buffer_end = (const char *)storage_ptr + storage_size; + m_owns_buffer = false; } - + /// @brief Destroys the SymbolDemangler and deallocates any scratch /// memory that it owns - + ~SymbolDemangler() { - if (owns_buffer) free(buffer); - if (owns_rewrite_ranges) free(rewrite_ranges); + if (m_owns_buffer) + free(m_buffer); + if (m_owns_m_rewrite_ranges) + free(m_rewrite_ranges); } - + #ifdef DEBUG_HIGHWATER int highwater_store = 0; int highwater_buffer = 0; #endif - + /// @brief Parses the provided mangled name and returns a newly allocated /// demangling /// @@ -161,293 +163,334 @@ public: /// @result Newly allocated null-terminated demangled name when demangling /// is succesful, and nullptr when demangling fails. The caller is /// responsible for freeing the allocated memory. - - char * GetDemangledCopy(const char * mangled_name, - long mangled_name_length = 0) + + char * + GetDemangledCopy(const char *mangled_name, + long mangled_name_length = 0) { - if (!ParseMangling(mangled_name, mangled_name_length)) return nullptr; - + if (!ParseMangling(mangled_name, mangled_name_length)) + return nullptr; + #ifdef DEBUG_HIGHWATER - int rewrite_count = next_substitute_index + - (rewrite_ranges_size - 1 - next_template_arg_index); - int buffer_size = (int)(write_ptr - buffer); - if (rewrite_count > highwater_store) highwater_store = rewrite_count; - if (buffer_size > highwater_buffer) highwater_buffer = buffer_size; + int rewrite_count = m_next_substitute_index + + (m_rewrite_ranges_size - 1 - m_next_template_arg_index); + int buffer_size = (int)(m_write_ptr - m_buffer); + if (rewrite_count > highwater_store) + highwater_store = rewrite_count; + if (buffer_size > highwater_buffer) + highwater_buffer = buffer_size; #endif - - int length = (int)(write_ptr - buffer); - char * copy = (char *)malloc(length + 1); - memcpy(copy, buffer, length); + + int length = (int)(m_write_ptr - m_buffer); + char *copy = (char *)malloc(length + 1); + memcpy(copy, m_buffer, length); copy[length] = '\0'; return copy; } - + private: - + //---------------------------------------------------- // Grow methods // // Manage the storage used during demangling //---------------------------------------------------- - + void GrowBuffer(long min_growth = 0) { // By default, double the size of the buffer - long growth = buffer_end - buffer; - + long growth = m_buffer_end - m_buffer; + // Avoid growing by more than 1MB at a time - if (growth > 1 << 20) growth = 1 << 20; - + if (growth > 1 << 20) + growth = 1 << 20; + // ... but never grow by less than requested, // or 1K, whichever is greater - if (min_growth < 1024) min_growth = 1024; - if (growth < min_growth) growth = min_growth; - - // Allocate the new buffer and migrate content - long new_size = (buffer_end - buffer) + growth; - char * new_buffer = (char *)malloc(new_size); - memcpy(new_buffer, buffer, write_ptr - buffer); - if (owns_buffer) free(buffer); - owns_buffer = true; - + if (min_growth < 1024) + min_growth = 1024; + if (growth < min_growth) + growth = min_growth; + + // Allocate the new m_buffer and migrate content + long new_size = (m_buffer_end - m_buffer) + growth; + char *new_buffer = (char *) malloc(new_size); + memcpy(new_buffer, m_buffer, m_write_ptr - m_buffer); + if (m_owns_buffer) + free(m_buffer); + m_owns_buffer = true; + // Update references to the new buffer - write_ptr = new_buffer + (write_ptr - buffer); - buffer = new_buffer; - buffer_end = buffer + new_size; + m_write_ptr = new_buffer + (m_write_ptr - m_buffer); + m_buffer = new_buffer; + m_buffer_end = m_buffer + new_size; } - - void GrowRewriteRanges() + + void + GrowRewriteRanges() { // By default, double the size of the array - int growth = rewrite_ranges_size; - + int growth = m_rewrite_ranges_size; + // Apply reasonable minimum and maximum sizes for growth - if (growth > 128) growth = 128; - if (growth < 16) growth = 16; - + if (growth > 128) + growth = 128; + if (growth < 16) + growth = 16; + // Allocate the new array and migrate content - int bytes = (rewrite_ranges_size + growth) * sizeof(BufferRange); - BufferRange * new_ranges = (BufferRange *) malloc(bytes); - for (int index = 0; index < next_substitute_index; index++) + int bytes = (m_rewrite_ranges_size + growth) * sizeof (BufferRange); + BufferRange *new_ranges = (BufferRange *) malloc (bytes); + for (int index = 0; index < m_next_substitute_index; index++) { - new_ranges[index] = rewrite_ranges[index]; + new_ranges[index] = m_rewrite_ranges[index]; } - for (int index = rewrite_ranges_size - 1; - index > next_template_arg_index; index--) + for (int index = m_rewrite_ranges_size - 1; + index > m_next_template_arg_index; index--) { - new_ranges[index + growth] = rewrite_ranges[index]; + new_ranges[index + growth] = m_rewrite_ranges[index]; } - if (owns_rewrite_ranges) free(rewrite_ranges); - owns_rewrite_ranges = true; - + if (m_owns_m_rewrite_ranges) + free(m_rewrite_ranges); + m_owns_m_rewrite_ranges = true; + // Update references to the new array - rewrite_ranges = new_ranges; - rewrite_ranges_size += growth; - next_template_arg_index += growth; + m_rewrite_ranges = new_ranges; + m_rewrite_ranges_size += growth; + m_next_template_arg_index += growth; } - + //---------------------------------------------------- // Range and state management //---------------------------------------------------- - - int GetStartCookie() + + int + GetStartCookie() { - return (int)(write_ptr - buffer); + return (int)(m_write_ptr - m_buffer); } - - BufferRange EndRange(int start_cookie) + + BufferRange + EndRange(int start_cookie) { - return { start_cookie, (int)(write_ptr - (buffer + start_cookie)) }; + return { start_cookie, (int)(m_write_ptr - (m_buffer + start_cookie)) }; } - - void ReorderRange(BufferRange source_range, int insertion_point_cookie) + + void + ReorderRange(BufferRange source_range, int insertion_point_cookie) { // Ensure there's room the preserve the source range - if (write_ptr + source_range.length > buffer_end) + if (m_write_ptr + source_range.length > m_buffer_end) { - GrowBuffer(write_ptr + source_range.length - buffer_end); + GrowBuffer(m_write_ptr + source_range.length - m_buffer_end); } - + // Reorder the content - memcpy(write_ptr, buffer + source_range.offset, source_range.length); - memmove(buffer + insertion_point_cookie + source_range.length, - buffer + insertion_point_cookie, + memcpy(m_write_ptr, m_buffer + source_range.offset, source_range.length); + memmove(m_buffer + insertion_point_cookie + source_range.length, + m_buffer + insertion_point_cookie, source_range.offset - insertion_point_cookie); - memcpy(buffer + insertion_point_cookie, write_ptr, source_range.length); - + memcpy(m_buffer + insertion_point_cookie, m_write_ptr, source_range.length); + // Fix up rewritable ranges, covering both substitutions and templates int index = 0; while (true) { - if (index == next_substitute_index) index = next_template_arg_index + 1; - if (index == rewrite_ranges_size) break; - + if (index == m_next_substitute_index) + index = m_next_template_arg_index + 1; + if (index == m_rewrite_ranges_size) + break; + // Affected ranges are either shuffled forward when after the // insertion but before the source, or backward when inside the // source - int candidate_offset = rewrite_ranges[index].offset; + int candidate_offset = m_rewrite_ranges[index].offset; if (candidate_offset >= insertion_point_cookie) { if (candidate_offset < source_range.offset) { - rewrite_ranges[index].offset += source_range.length; + m_rewrite_ranges[index].offset += source_range.length; } else if (candidate_offset >= source_range.offset) { - rewrite_ranges[index].offset -= - (source_range.offset - insertion_point_cookie); + m_rewrite_ranges[index].offset -= (source_range.offset - insertion_point_cookie); } } ++index; } } - - void EndSubstitution(int start_cookie) + + void + EndSubstitution(int start_cookie) { - if (next_substitute_index == next_template_arg_index) GrowRewriteRanges(); - - int index = next_substitute_index++; - rewrite_ranges[index] = EndRange(start_cookie); + if (m_next_substitute_index == m_next_template_arg_index) + GrowRewriteRanges(); + + int index = m_next_substitute_index++; + m_rewrite_ranges[index] = EndRange(start_cookie); #ifdef DEBUG_SUBSTITUTIONS printf("Saved substitution # %d = %.*s\n", index, - rewrite_ranges[index].length, buffer + start_cookie); + m_rewrite_ranges[index].length, m_buffer + start_cookie); #endif } - - void EndTemplateArg(int start_cookie) + + void + EndTemplateArg(int start_cookie) { - if (next_substitute_index == next_template_arg_index) GrowRewriteRanges(); - - int index = next_template_arg_index--; - rewrite_ranges[index] = EndRange(start_cookie); + if (m_next_substitute_index == m_next_template_arg_index) + GrowRewriteRanges(); + + int index = m_next_template_arg_index--; + m_rewrite_ranges[index] = EndRange(start_cookie); #ifdef DEBUG_TEMPLATE_ARGS printf("Saved template arg # %d = %.*s\n", - rewrite_ranges_size - index - 1, - rewrite_ranges[index].length, buffer + start_cookie); + m_rewrite_ranges_size - index - 1, + m_rewrite_ranges[index].length, m_buffer + start_cookie); #endif } - - void ResetTemplateArgs() + + void + ResetTemplateArgs() { //TODO: this works, but is it the right thing to do? // Should we push/pop somehow at the call sites? - next_template_arg_index = rewrite_ranges_size - 1; + m_next_template_arg_index = m_rewrite_ranges_size - 1; } - + //---------------------------------------------------- // Write methods // // Appends content to the existing output buffer //---------------------------------------------------- - - void Write(char character) + + void + Write(char character) { - if (write_ptr == buffer_end) GrowBuffer(); - *write_ptr++ = character; + if (m_write_ptr == m_buffer_end) + GrowBuffer(); + *m_write_ptr++ = character; } - - void Write(const char * content) + + void + Write(const char *content) { Write(content, strlen(content)); } - - void Write(const char * content, long content_length) + + void + Write(const char *content, long content_length) { - char * end_write_ptr = write_ptr + content_length; - if (end_write_ptr > buffer_end) + char *end_m_write_ptr = m_write_ptr + content_length; + if (end_m_write_ptr > m_buffer_end) { - GrowBuffer(end_write_ptr - buffer_end); - end_write_ptr = write_ptr + content_length; + GrowBuffer(end_m_write_ptr - m_buffer_end); + end_m_write_ptr = m_write_ptr + content_length; } - memcpy(write_ptr, content, content_length); - write_ptr = end_write_ptr; + memcpy(m_write_ptr, content, content_length); + m_write_ptr = end_m_write_ptr; } -#define WRITE(x) Write(x, sizeof(x) - 1) - - void WriteTemplateStart() +#define WRITE(x) Write(x, sizeof (x) - 1) + + void + WriteTemplateStart() { Write('<'); } - - void WriteTemplateEnd() + + void + WriteTemplateEnd() { // Put a space between terminal > characters when nesting templates - if (write_ptr != buffer && *(write_ptr - 1) == '>') WRITE(" >"); + if (m_write_ptr != m_buffer && *(m_write_ptr - 1) == '>') + WRITE(" >"); else Write('>'); } - - void WriteCommaSpace() + + void + WriteCommaSpace() { WRITE(", "); } - - void WriteNamespaceSeparator() + + void + WriteNamespaceSeparator() { WRITE("::"); } - - void WriteStdPrefix() + + void + WriteStdPrefix() { WRITE("std::"); } - - void WriteQualifiers(int qualifiers, bool space_before_reference = true) - { - if (qualifiers & QualifierPointer) Write('*'); - if (qualifiers & QualifierConst) WRITE(" const"); - if (qualifiers & QualifierVolatile) WRITE(" volatile"); - if (qualifiers & QualifierRestrict) WRITE(" restrict"); + + void + WriteQualifiers(int qualifiers, bool space_before_reference = true) + { + if (qualifiers & QualifierPointer) + Write('*'); + if (qualifiers & QualifierConst) + WRITE(" const"); + if (qualifiers & QualifierVolatile) + WRITE(" volatile"); + if (qualifiers & QualifierRestrict) + WRITE(" restrict"); if (qualifiers & QualifierReference) { - if (space_before_reference) WRITE(" &"); + if (space_before_reference) + WRITE(" &"); else Write('&'); } if (qualifiers & QualifierRValueReference) { - if (space_before_reference) WRITE(" &&"); + if (space_before_reference) + WRITE(" &&"); else WRITE("&&"); } } - + //---------------------------------------------------- // Rewrite methods // // Write another copy of content already present // earlier in the output buffer //---------------------------------------------------- - - void RewriteRange(BufferRange range) + + void + RewriteRange(BufferRange range) { - Write(buffer + range.offset, range.length); + Write(m_buffer + range.offset, range.length); } - - bool RewriteSubstitution(int index) + + bool + RewriteSubstitution(int index) { - if (index < 0 || index >= next_substitute_index) + if (index < 0 || index >= m_next_substitute_index) { #ifdef DEBUG_FAILURES printf("*** Invalid substitution #%d\n", index); #endif return false; } - RewriteRange(rewrite_ranges[index]); + RewriteRange(m_rewrite_ranges[index]); return true; } - - bool RewriteTemplateArg(int template_index) + + bool + RewriteTemplateArg(int template_index) { - int index = rewrite_ranges_size - 1 - template_index; - if (template_index < 0 || index <= next_template_arg_index) + int index = m_rewrite_ranges_size - 1 - template_index; + if (template_index < 0 || index <= m_next_template_arg_index) { #ifdef DEBUG_FAILURES printf("*** Invalid template arg reference #%d\n", template_index); #endif return false; } - RewriteRange(rewrite_ranges[index]); + RewriteRange(m_rewrite_ranges[index]); return true; } - + //---------------------------------------------------- // TryParse methods // @@ -455,45 +498,53 @@ private: // writing to the output buffer // // Values indicating failure guarantee that the pre- - // call read_ptr is unchanged + // call m_read_ptr is unchanged //---------------------------------------------------- - - int TryParseNumber() + + int + TryParseNumber() { - unsigned char digit = *read_ptr - '0'; - if (digit > 9) return -1; - + unsigned char digit = *m_read_ptr - '0'; + if (digit > 9) + return -1; + int count = digit; while (true) { - digit = *++read_ptr - '0'; - if (digit > 9) break; - + digit = *++m_read_ptr - '0'; + if (digit > 9) + break; + count = count * 10 + digit; } return count; } - - int TryParseBase36Number() + + int + TryParseBase36Number() { - char digit = *read_ptr; + char digit = *m_read_ptr; int count; - if (digit >= '0' && digit <= '9') count = digit -= '0'; - else if (digit >= 'A' && digit <= 'Z') count = digit -= ('A' - 10); + if (digit >= '0' && digit <= '9') + count = digit -= '0'; + else if (digit >= 'A' && digit <= 'Z') + count = digit -= ('A' - 10); else return -1; - + while (true) { - digit = *++read_ptr; - if (digit >= '0' && digit <= '9') digit -= '0'; - else if (digit >= 'A' && digit <= 'Z') digit -= ('A' - 10); + digit = *++m_read_ptr; + if (digit >= '0' && digit <= '9') + digit -= '0'; + else if (digit >= 'A' && digit <= 'Z') + digit -= ('A' - 10); else break; - + count = count * 36 + digit; } return count; } - + // ::= v # void // ::= w # wchar_t // ::= b # bool @@ -524,10 +575,11 @@ private: // ::= Da # auto (in dependent new-expressions) // ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) // ::= u # vendor extended type - - const char * TryParseBuiltinType() + + const char * + TryParseBuiltinType() { - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'v': return "void"; case 'w': return "wchar_t"; @@ -552,7 +604,7 @@ private: case 'z': return "..."; case 'D': { - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'd': return "decimal64"; case 'e': return "decimal128"; @@ -564,14 +616,14 @@ private: case 'c': return "decltype(auto)"; case 'n': return "std::nullptr_t"; default: - --read_ptr; + --m_read_ptr; } } } - --read_ptr; + --m_read_ptr; return nullptr; } - + // // ::= aa # && // ::= ad # & (unary) @@ -622,13 +674,14 @@ private: // ::= rS # >>= // ::= cv # (cast) // ::= v # vendor extended operator - - Operator TryParseOperator() + + Operator + TryParseOperator() { - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'a': - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'a': return { "&&", OperatorKind::Binary }; case 'd': return { "&", OperatorKind::Unary }; @@ -636,20 +689,20 @@ private: case 'N': return { "&=", OperatorKind::Binary }; case 'S': return { "=", OperatorKind::Binary }; } - --read_ptr; + --m_read_ptr; break; case 'c': - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'l': return { "()", OperatorKind::Other }; case 'm': return { ",", OperatorKind::Other }; case 'o': return { "~", OperatorKind::Unary }; case 'v': return { nullptr, OperatorKind::ConversionOperator }; } - --read_ptr; + --m_read_ptr; break; case 'd': - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'a': return { " delete[]", OperatorKind::Other }; case 'e': return { "*", OperatorKind::Unary }; @@ -657,34 +710,34 @@ private: case 'v': return { "/", OperatorKind::Binary }; case 'V': return { "/=", OperatorKind::Binary }; } - --read_ptr; + --m_read_ptr; break; case 'e': - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'o': return { "^", OperatorKind::Binary }; case 'O': return { "^=", OperatorKind::Binary }; case 'q': return { "==", OperatorKind::Binary }; } - --read_ptr; + --m_read_ptr; break; case 'g': - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'e': return { ">=", OperatorKind::Binary }; case 't': return { ">", OperatorKind::Binary }; } - --read_ptr; + --m_read_ptr; break; case 'i': - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'x': return { "[]", OperatorKind::Other }; } - --read_ptr; + --m_read_ptr; break; case 'l': - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'e': return { "<=", OperatorKind::Binary }; case 's': return { "<<", OperatorKind::Binary }; @@ -692,10 +745,10 @@ private: case 't': return { "<", OperatorKind::Binary }; // case 'i': return { "?", OperatorKind::Binary }; } - --read_ptr; + --m_read_ptr; break; case 'm': - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'i': return { "-", OperatorKind::Binary }; case 'I': return { "-=", OperatorKind::Binary }; @@ -703,10 +756,10 @@ private: case 'L': return { "*=", OperatorKind::Binary }; case 'm': return { "--", OperatorKind::Postfix }; } - --read_ptr; + --m_read_ptr; break; case 'n': - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'a': return { " new[]", OperatorKind::Other }; case 'e': return { "!=", OperatorKind::Binary }; @@ -714,19 +767,19 @@ private: case 't': return { "!", OperatorKind::Unary }; case 'w': return { " new", OperatorKind::Other }; } - --read_ptr; + --m_read_ptr; break; case 'o': - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'o': return { "||", OperatorKind::Binary }; case 'r': return { "|", OperatorKind::Binary }; case 'R': return { "|=", OperatorKind::Binary }; } - --read_ptr; + --m_read_ptr; break; case 'p': - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'm': return { "->*", OperatorKind::Binary }; case 's': return { "+", OperatorKind::Unary }; @@ -735,154 +788,161 @@ private: case 'p': return { "++", OperatorKind::Postfix }; case 't': return { "->", OperatorKind::Binary }; } - --read_ptr; + --m_read_ptr; break; case 'q': - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'u': return { "?", OperatorKind::Ternary }; } - --read_ptr; + --m_read_ptr; break; case 'r': - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'm': return { "%", OperatorKind::Binary }; case 'M': return { "%=", OperatorKind::Binary }; case 's': return { ">>", OperatorKind::Binary }; case 'S': return { ">=", OperatorKind::Binary }; } - --read_ptr; + --m_read_ptr; break; case 'v': - char digit = *read_ptr; + char digit = *m_read_ptr; if (digit >= '0' && digit <= '9') { - read_ptr++; + m_read_ptr++; return { nullptr, OperatorKind::Vendor }; } - --read_ptr; + --m_read_ptr; break; } - --read_ptr; + --m_read_ptr; return { nullptr, OperatorKind::NoMatch }; } - + // ::= [r] [V] [K] // ::= R # & ref-qualifier // ::= O # && ref-qualifier - - int TryParseQualifiers(bool allow_cv, bool allow_ro) + + int + TryParseQualifiers(bool allow_cv, bool allow_ro) { int qualifiers = QualifierNone; - char next = *read_ptr; + char next = *m_read_ptr; if (allow_cv) { if (next == 'r') // restrict { qualifiers |= QualifierRestrict; - next = *++read_ptr; + next = *++m_read_ptr; } if (next == 'V') // volatile { qualifiers |= QualifierVolatile; - next = *++read_ptr; + next = *++m_read_ptr; } if (next == 'K') // const { qualifiers |= QualifierConst; - next = *++read_ptr; + next = *++m_read_ptr; } } if (allow_ro) { if (next == 'R') { - ++read_ptr; + ++m_read_ptr; qualifiers |= QualifierReference; } else if (next =='O') { - ++read_ptr; + ++m_read_ptr; qualifiers |= QualifierRValueReference; } } return qualifiers; } - + // := _ # when number < 10 // := __ _ # when number >= 10 // extension := decimal-digit+ - - int TryParseDiscriminator() + + int + TryParseDiscriminator() { - const char * discriminator_start = read_ptr; - + const char *discriminator_start = m_read_ptr; + // Test the extension first, since it's what Clang uses int discriminator_value = TryParseNumber(); - if (discriminator_value != -1) return discriminator_value; - - char next = *read_ptr; + if (discriminator_value != -1) + return discriminator_value; + + char next = *m_read_ptr; if (next == '_') { - next = *++read_ptr; + next = *++m_read_ptr; if (next == '_') { - ++read_ptr; + ++m_read_ptr; discriminator_value = TryParseNumber(); - if (discriminator_value != -1 && *read_ptr++ != '_') + if (discriminator_value != -1 && *m_read_ptr++ != '_') { return discriminator_value; } } else if (next >= '0' && next <= '9') { - ++read_ptr; + ++m_read_ptr; return next - '0'; } } - + // Not a valid discriminator - read_ptr = discriminator_start; + m_read_ptr = discriminator_start; return -1; } - + //---------------------------------------------------- // Parse methods // - // Consume input starting from read_ptr and produce - // buffered output at write_ptr + // Consume input starting from m_read_ptr and produce + // buffered output at m_write_ptr // - // Failures return false and may leave read_ptr in an + // Failures return false and may leave m_read_ptr in an // indeterminate state //---------------------------------------------------- - - bool Parse(char character) + + bool + Parse(char character) { - if (*read_ptr++ == character) return true; + if (*m_read_ptr++ == character) + return true; #ifdef DEBUG_FAILURES printf("*** Expected '%c'\n", character); #endif return false; } - + // ::= [n] - - bool ParseNumber(bool allow_negative = false) + + bool + ParseNumber(bool allow_negative = false) { - if (allow_negative && *read_ptr == 'n') + if (allow_negative && *m_read_ptr == 'n') { Write('-'); - ++read_ptr; + ++m_read_ptr; } - const char * before_digits = read_ptr; + const char *before_digits = m_read_ptr; while (true) { - unsigned char digit = *read_ptr - '0'; - if (digit > 9) break; - ++read_ptr; + unsigned char digit = *m_read_ptr - '0'; + if (digit > 9) + break; + ++m_read_ptr; } - if (int digit_count = (int)(read_ptr - before_digits)) + if (int digit_count = (int)(m_read_ptr - before_digits)) { Write(before_digits, digit_count); return true; @@ -892,7 +952,7 @@ private: #endif return false; } - + // ::= S _ // ::= S_ // ::= Sa # ::std::allocator @@ -903,11 +963,12 @@ private: // ::= Si # ::std::basic_istream > // ::= So # ::std::basic_ostream > // ::= Sd # ::std::basic_iostream > - - bool ParseSubstitution() + + bool + ParseSubstitution() { - const char * substitution; - switch (*read_ptr) + const char *substitution; + switch (*m_read_ptr) { case 'a': substitution = "std::allocator"; break; case 'b': substitution = "std::basic_string"; break; @@ -919,25 +980,26 @@ private: // A failed attempt to parse a number will return -1 which turns out to be // perfect here as S_ is the first substitution, S0_ the next and so forth int substitution_index = TryParseBase36Number(); - if (*read_ptr++ != '_') + if (*m_read_ptr++ != '_') { #ifdef DEBUG_FAILURES printf("*** Expected terminal _ in substitution\n"); #endif return false; } - return RewriteSubstitution(substitution_index + 1); + return RewriteSubstitution (substitution_index + 1); } Write(substitution); - ++read_ptr; + ++m_read_ptr; return true; } - + // ::= F [Y] [] E // // ::= + # types are possible return type, then parameter types - - bool ParseFunctionType(int inner_qualifiers = QualifierNone) + + bool + ParseFunctionType (int inner_qualifiers = QualifierNone) { #ifdef DEBUG_FAILURES printf("*** Function types not supported\n"); @@ -947,70 +1009,77 @@ private: // int (*)() when used as the type for "name" becomes int (*name)(). // This makes substitution et al ... interesting. return false; - - if (*read_ptr == 'Y') ++read_ptr;; - + +#if 0 // TODO + if (*m_read_ptr == 'Y') + ++m_read_ptr; + int return_type_start_cookie = GetStartCookie(); - if (!ParseType()) return false; + if (!ParseType()) + return false; Write(' '); - + int insert_cookie = GetStartCookie(); Write('('); bool first_param = true; int qualifiers = QualifierNone; while (true) { - switch (*read_ptr) + switch (*m_read_ptr) { case 'E': - ++read_ptr; + ++m_read_ptr; Write(')'); break; case 'v': - ++read_ptr; + ++m_read_ptr; continue; case 'R': case 'O': - if (*(read_ptr + 1) == 'E') + if (*(m_read_ptr + 1) == 'E') { - qualifiers = TryParseQualifiers(false, true); + qualifiers = TryParseQualifiers (false, true); Parse('E'); break; } // fallthrough default: { - if (first_param) first_param = false; + if (first_param) + first_param = false; else WriteCommaSpace(); - - if (!ParseType()) return false; + + if (!ParseType()) + return false; continue; } } break; } - + if (qualifiers) { - WriteQualifiers(qualifiers); - EndSubstitution(return_type_start_cookie); + WriteQualifiers (qualifiers); + EndSubstitution (return_type_start_cookie); } - + if (inner_qualifiers) { int qualifier_start_cookie = GetStartCookie(); - Write('('); - WriteQualifiers(inner_qualifiers); - Write(')'); - ReorderRange(EndRange(qualifier_start_cookie), insert_cookie); + Write ('('); + WriteQualifiers (inner_qualifiers); + Write (')'); + ReorderRange (EndRange (qualifier_start_cookie), insert_cookie); } return true; +#endif // TODO } - + // ::= A _ // ::= A [] _ - - bool ParseArrayType(int qualifiers = QualifierNone) + + bool + ParseArrayType(int qualifiers = QualifierNone) { #ifdef DEBUG_FAILURES printf("*** Array type unsupported\n"); @@ -1021,26 +1090,32 @@ private: // //TODO: Chances are we don't do any better with references and pointers // that should be type (&) [] instead of type & [] - + return false; - - if (*read_ptr == '_') + +#if 0 // TODO + if (*m_read_ptr == '_') { - ++read_ptr; - if (!ParseType()) return false; - if (qualifiers) WriteQualifiers(qualifiers); + ++m_read_ptr; + if (!ParseType()) + return false; + if (qualifiers) + WriteQualifiers(qualifiers); WRITE(" []"); return true; } else { - const char * before_digits = read_ptr; + const char *before_digits = m_read_ptr; if (TryParseNumber() != -1) { - const char * after_digits = read_ptr; - if (!Parse('_')) return false; - if (!ParseType()) return false; - if (qualifiers) WriteQualifiers(qualifiers); + const char *after_digits = m_read_ptr; + if (!Parse('_')) + return false; + if (!ParseType()) + return false; + if (qualifiers) + WriteQualifiers(qualifiers); Write(' '); Write('['); Write(before_digits, after_digits - before_digits); @@ -1048,51 +1123,61 @@ private: else { int type_insertion_cookie = GetStartCookie(); - if (!ParseExpression()) return false; - if (!Parse('_')) return false; - + if (!ParseExpression()) + return false; + if (!Parse('_')) + return false; + int type_start_cookie = GetStartCookie(); - if (!ParseType()) return false; - if (qualifiers) WriteQualifiers(qualifiers); + if (!ParseType()) + return false; + if (qualifiers) + WriteQualifiers(qualifiers); Write(' '); Write('['); - ReorderRange(EndRange(type_start_cookie), type_insertion_cookie); + ReorderRange (EndRange (type_start_cookie), type_insertion_cookie); } Write(']'); return true; } +#endif // TODO } - + // ::= M - + //TODO: Determine how to handle pointers to function members correctly, // currently not an issue because we don't have function types at all... - bool ParsePointerToMemberType() + bool + ParsePointerToMemberType() { int insertion_cookie = GetStartCookie(); Write(' '); - if (!ParseType()) return false; + if (!ParseType()) + return false; WRITE("::*"); - + int type_cookie = GetStartCookie(); - if (!ParseType()) return false; - ReorderRange(EndRange(type_cookie), insertion_cookie); + if (!ParseType()) + return false; + ReorderRange (EndRange (type_cookie), insertion_cookie); return true; } - + // ::= T_ # first template parameter // ::= T _ - - bool ParseTemplateParam() + + bool + ParseTemplateParam() { int count = TryParseNumber(); - if (!Parse('_')) return false; - + if (!Parse('_')) + return false; + // When no number is present we get -1, which is convenient since // T_ is the zeroth element T0_ is element 1, and so on - return RewriteTemplateArg(count + 1); + return RewriteTemplateArg (count + 1); } - + // ::= // ::= // ::= @@ -1112,27 +1197,29 @@ private: // ::= U # vendor extended type qualifier // extension := U # objc-type // extension := # starts with Dv - + // ::= objcproto # k0 = 9 + + k1 // := # PU<11+>objcproto 11objc_object 11objc_object -> id - - bool ParseType() + + bool + ParseType() { #ifdef DEBUG_FAILURES - const char * failed_type = read_ptr; + const char *failed_type = m_read_ptr; #endif int type_start_cookie = GetStartCookie(); bool suppress_substitution = false; - - int qualifiers = TryParseQualifiers(true, false); - switch (*read_ptr) + + int qualifiers = TryParseQualifiers (true, false); + switch (*m_read_ptr) { case 'D': - ++read_ptr; - switch (*read_ptr++) + ++m_read_ptr; + switch (*m_read_ptr++) { case 'p': - if (!ParseType()) return false; + if (!ParseType()) + return false; break; case 'T': case 't': @@ -1145,44 +1232,52 @@ private: } break; case 'T': - ++read_ptr; - if (!ParseTemplateParam()) return false; + ++m_read_ptr; + if (!ParseTemplateParam()) + return false; break; case 'M': - ++read_ptr; - if (!ParsePointerToMemberType()) return false; + ++m_read_ptr; + if (!ParsePointerToMemberType()) + return false; break; case 'A': - ++read_ptr; - if (!ParseArrayType()) return false; + ++m_read_ptr; + if (!ParseArrayType()) + return false; break; case 'F': - ++read_ptr; - if (!ParseFunctionType()) return false; + ++m_read_ptr; + if (!ParseFunctionType()) + return false; break; case 'S': - if (*++read_ptr == 't') + if (*++m_read_ptr == 't') { - ++read_ptr; + ++m_read_ptr; WriteStdPrefix(); - if (!ParseName()) return false; + if (!ParseName()) + return false; } else { suppress_substitution = true; - if (!ParseSubstitution()) return false; + if (!ParseSubstitution()) + return false; } break; case 'P': { - switch (*++read_ptr) + switch (*++m_read_ptr) { case 'F': - ++read_ptr; - if (!ParseFunctionType(QualifierPointer)) return false; + ++m_read_ptr; + if (!ParseFunctionType(QualifierPointer)) + return false; break; default: - if (!ParseType()) return false; + if (!ParseType()) + return false; Write('*'); break; } @@ -1190,15 +1285,17 @@ private: } case 'R': { - ++read_ptr; - if (!ParseType()) return false; + ++m_read_ptr; + if (!ParseType()) + return false; Write('&'); break; } case 'O': { - ++read_ptr; - if (!ParseType()) return false; + ++m_read_ptr; + if (!ParseType()) + return false; Write('&'); Write('&'); break; @@ -1214,24 +1311,27 @@ private: case 'N': case 'Z': case 'L': - if (!ParseName()) return false; + if (!ParseName()) + return false; break; default: - if (const char * builtin = TryParseBuiltinType()) + if (const char *builtin = TryParseBuiltinType()) { Write(builtin); suppress_substitution = true; } else { - if (!ParseName()) return false; + if (!ParseName()) + return false; } break; } - + // Allow base substitutions to be suppressed, but always record // substitutions for the qualified variant - if (!suppress_substitution) EndSubstitution(type_start_cookie); + if (!suppress_substitution) + EndSubstitution(type_start_cookie); if (qualifiers) { WriteQualifiers(qualifiers, false); @@ -1239,40 +1339,43 @@ private: } return true; } - + // ::= Ut [ ] _ // ::= // // ::= Ul E [ ] _ // // ::= + # Parameter types or "v" if the lambda has no parameters - - bool ParseUnnamedTypeName(NameState & name_state) + + bool + ParseUnnamedTypeName(NameState & name_state) { - switch (*read_ptr++) + switch (*m_read_ptr++) { case 't': { int cookie = GetStartCookie(); WRITE("'unnamed"); - const char * before_digits = read_ptr; - if (TryParseNumber() != -1) Write(before_digits, - read_ptr - before_digits); - if (!Parse('_')) return false; + const char *before_digits = m_read_ptr; + if (TryParseNumber() != -1) Write (before_digits, + m_read_ptr - before_digits); + if (!Parse('_')) + return false; Write('\''); - name_state.last_name_range = EndRange(cookie); + name_state.last_name_range = EndRange (cookie); return true; } case 'b': { int cookie = GetStartCookie(); WRITE("'block"); - const char * before_digits = read_ptr; - if (TryParseNumber() != -1) Write(before_digits, - read_ptr - before_digits); - if (!Parse('_')) return false; + const char *before_digits = m_read_ptr; + if (TryParseNumber() != -1) Write (before_digits, + m_read_ptr - before_digits); + if (!Parse('_')) + return false; Write('\''); - name_state.last_name_range = EndRange(cookie); + name_state.last_name_range = EndRange (cookie); return true; } case 'l': @@ -1282,23 +1385,24 @@ private: return false; } #ifdef DEBUG_FAILURES - printf("*** Unknown unnamed type %.3s\n", read_ptr - 2); + printf("*** Unknown unnamed type %.3s\n", m_read_ptr - 2); #endif return false; } - + // ::= C1 # complete object constructor // ::= C2 # base object constructor // ::= C3 # complete object allocating constructor - - bool ParseCtor(NameState & name_state) + + bool + ParseCtor(NameState & name_state) { - char next = *read_ptr; + char next = *m_read_ptr; if (next == '1' || next == '2' || next == '3' || next == '5') { - RewriteRange(name_state.last_name_range); + RewriteRange (name_state.last_name_range); name_state.has_no_return_type = true; - ++read_ptr; + ++m_read_ptr; return true; } #ifdef DEBUG_FAILURES @@ -1306,20 +1410,21 @@ private: #endif return false; } - + // ::= D0 # deleting destructor // ::= D1 # complete object destructor // ::= D2 # base object destructor - - bool ParseDtor(NameState & name_state) + + bool + ParseDtor(NameState & name_state) { - char next = *read_ptr; + char next = *m_read_ptr; if (next == '0' || next == '1' || next == '2' || next == '5') { Write('~'); RewriteRange(name_state.last_name_range); name_state.has_no_return_type = true; - ++read_ptr; + ++m_read_ptr; return true; } #ifdef DEBUG_FAILURES @@ -1327,13 +1432,14 @@ private: #endif return false; } - + // See TryParseOperator() - - bool ParseOperatorName(NameState & name_state) + + bool + ParseOperatorName(NameState & name_state) { #ifdef DEBUG_FAILURES - const char * operator_ptr = read_ptr; + const char *operator_ptr = m_read_ptr; #endif Operator parsed_operator = TryParseOperator(); if (parsed_operator.name) @@ -1342,7 +1448,7 @@ private: Write(parsed_operator.name); return true; } - + // Handle special operators switch (parsed_operator.kind) { @@ -1361,10 +1467,11 @@ private: return false; } } - + // ::= - - bool ParseSourceName() + + bool + ParseSourceName() { int count = TryParseNumber(); if (count == -1) @@ -1374,43 +1481,45 @@ private: #endif return false; } - - const char * next_read_ptr = read_ptr + count; - if (next_read_ptr > read_end) + + const char *next_m_read_ptr = m_read_ptr + count; + if (next_m_read_ptr > m_read_end) { #ifdef DEBUG_FAILURES printf("*** Malformed source name, premature termination\n"); #endif return false; } - - if (count >= 10 && strncmp(read_ptr, "_GLOBAL__N", 10) == 0) WRITE("(anonymous namespace)"); - else Write(read_ptr, count); - - read_ptr = next_read_ptr; + + if (count >= 10 && strncmp(m_read_ptr, "_GLOBAL__N", 10) == 0) + WRITE("(anonymous namespace)"); + else Write(m_read_ptr, count); + + m_read_ptr = next_m_read_ptr; return true; } - + // ::= // ::= // ::= // ::= - - bool ParseUnqualifiedName(NameState & name_state) + + bool + ParseUnqualifiedName(NameState & name_state) { // Note that these are detected directly in ParseNestedName for // performance rather than switching on the same options twice - char next = *read_ptr; + char next = *m_read_ptr; switch (next) { case 'C': - ++read_ptr; + ++m_read_ptr; return ParseCtor(name_state); case 'D': - ++read_ptr; + ++m_read_ptr; return ParseDtor(name_state); case 'U': - ++read_ptr; + ++m_read_ptr; return ParseUnnamedTypeName(name_state); case '0': case '1': @@ -1424,7 +1533,8 @@ private: case '9': { int name_start_cookie = GetStartCookie(); - if (!ParseSourceName()) return false; + if (!ParseSourceName()) + return false; name_state.last_name_range = EndRange(name_start_cookie); return true; } @@ -1432,33 +1542,40 @@ private: return ParseOperatorName(name_state); }; } - + // ::= // ::= St # ::std:: // extension ::= StL - - bool ParseUnscopedName(NameState & name_state) + + bool + ParseUnscopedName(NameState & name_state) { - if (*read_ptr == 'S' && *(read_ptr + 1) == 't') + if (*m_read_ptr == 'S' && *(m_read_ptr + 1) == 't') { WriteStdPrefix(); - if (*(read_ptr += 2) == 'L') ++read_ptr; + if (*(m_read_ptr += 2) == 'L') + ++m_read_ptr; } return ParseUnqualifiedName(name_state); } - - bool ParseIntegerLiteral(const char * prefix, const char * suffix, + + bool + ParseIntegerLiteral(const char *prefix, const char *suffix, bool allow_negative) { - if (prefix) Write(prefix); - if (!ParseNumber(allow_negative)) return false; - if (suffix) Write(suffix); + if (prefix) + Write(prefix); + if (!ParseNumber(allow_negative)) + return false; + if (suffix) + Write(suffix); return Parse('E'); } - - bool ParseBooleanLiteral() + + bool + ParseBooleanLiteral() { - switch (*read_ptr++) + switch (*m_read_ptr++) { case '0': WRITE("false"); break; case '1': WRITE("true"); break; @@ -1470,17 +1587,18 @@ private: } return Parse('E'); } - + // ::= L E # integer literal // ::= L E # floating literal // ::= L E # string literal // ::= L E # nullptr literal (i.e., "LDnE") // ::= L _ E # complex floating point literal (C 2000) // ::= L E # external name - - bool ParseExpressionPrimary() + + bool + ParseExpressionPrimary() { - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'b': return ParseBooleanLiteral(); case 'x': return ParseIntegerLiteral(nullptr, "ll", true); @@ -1493,12 +1611,13 @@ private: case 'o': return ParseIntegerLiteral("(unsigned __int128)", nullptr, false); case '_': - if (*read_ptr++ == 'Z') + if (*m_read_ptr++ == 'Z') { - if (!ParseEncoding()) return false; + if (!ParseEncoding()) + return false; return Parse('E'); } - --read_ptr; + --m_read_ptr; // fallthrough case 'w': case 'c': @@ -1510,7 +1629,7 @@ private: case 'd': case 'e': #ifdef DEBUG_FAILURES - printf("*** Unsupported primary expression %.5s\n", read_ptr - 1); + printf("*** Unsupported primary expression %.5s\n", m_read_ptr - 1); #endif return false; case 'T': @@ -1521,49 +1640,55 @@ private: #endif return false; default: - --read_ptr; + --m_read_ptr; Write('('); - if (!ParseType()) return false; + if (!ParseType()) + return false; Write(')'); - if (!ParseNumber()) return false; + if (!ParseNumber()) + return false; return Parse('E'); } } - + // ::= // ::= // ::= - - bool ParseUnresolvedType() + + bool + ParseUnresolvedType() { int type_start_cookie = GetStartCookie(); - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'T': - if (!ParseTemplateParam()) return false; + if (!ParseTemplateParam()) + return false; EndSubstitution(type_start_cookie); return true; case 'S': { - if (*read_ptr != 't') return ParseSubstitution(); - - ++read_ptr; + if (*m_read_ptr != 't') + return ParseSubstitution(); + + ++m_read_ptr; WriteStdPrefix(); NameState type_name = {}; - if (!ParseUnqualifiedName(type_name)) return false; + if (!ParseUnqualifiedName(type_name)) + return false; EndSubstitution(type_start_cookie); return true; - + } case 'D': default: #ifdef DEBUG_FAILURES - printf("*** Unsupported unqualified type: %3s\n", read_ptr - 1); + printf("*** Unsupported unqualified type: %3s\n", m_read_ptr - 1); #endif return false; } } - + // ::= # unresolved name // extension ::= # unresolved operator-function-id // extension ::= # unresolved operator template-id @@ -1571,15 +1696,16 @@ private: // ::= on # unresolved operator template-id // ::= dn # destructor or pseudo-destructor; // # e.g. ~X or ~X - - bool ParseBaseUnresolvedName() + + bool + ParseBaseUnresolvedName() { #ifdef DEBUG_FAILURES printf("*** Base unresolved name unsupported\n"); #endif return false; } - + // // extension ::= srN [] * E // ::= [gs] # x or (with "gs") ::x @@ -1589,22 +1715,25 @@ private: // extension ::= sr // # T::N::x /decltype(p)::N::x // (ignored) ::= srN + E - - bool ParseUnresolvedName() + + bool + ParseUnresolvedName() { #ifdef DEBUG_FAILURES printf("*** Unresolved names not supported\n"); #endif //TODO: grammar for all of this seems unclear... return false; - - if (*read_ptr == 'g' && *(read_ptr + 1) == 's') + +#if 0 // TODO + if (*m_read_ptr == 'g' && *(m_read_ptr + 1) == 's') { - read_ptr += 2; + m_read_ptr += 2; WriteNamespaceSeparator(); } +#endif // TODO } - + // ::= // ::= // ::= @@ -1644,8 +1773,9 @@ private: // # freestanding dependent name (e.g., T::x), // # objectless nonstatic member reference // ::= - - bool ParseExpression() + + bool + ParseExpression() { Operator expression_operator = TryParseOperator(); switch (expression_operator.kind) @@ -1653,17 +1783,21 @@ private: case OperatorKind::Unary: Write(expression_operator.name); Write('('); - if (!ParseExpression()) return false; + if (!ParseExpression()) + return false; Write(')'); return true; case OperatorKind::Binary: - if (!ParseExpression()) return false; + if (!ParseExpression()) + return false; Write(expression_operator.name); return ParseExpression(); case OperatorKind::Ternary: - if (!ParseExpression()) return false; + if (!ParseExpression()) + return false; Write('?'); - if (!ParseExpression()) return false; + if (!ParseExpression()) + return false; Write(':'); return ParseExpression(); case OperatorKind::NoMatch: @@ -1675,67 +1809,75 @@ private: #endif return false; } - - switch (*read_ptr++) + + switch (*m_read_ptr++) { case 'T': return ParseTemplateParam(); case 'L': return ParseExpressionPrimary(); case 's': - if (*read_ptr++ == 'r') return ParseUnresolvedName(); - --read_ptr; + if (*m_read_ptr++ == 'r') + return ParseUnresolvedName(); + --m_read_ptr; // fallthrough default: return ParseExpressionPrimary(); } } - + // ::= # type or template // ::= X E # expression // ::= # simple expressions // ::= J * E # argument pack // ::= LZ E # extension - - bool ParseTemplateArg() + + bool + ParseTemplateArg() { - switch (*read_ptr) { + switch (*m_read_ptr) { case 'J': #ifdef DEBUG_FAILURES printf("*** Template argument packs unsupported\n"); #endif return false; case 'X': - ++read_ptr; - if (!ParseExpression()) return false; + ++m_read_ptr; + if (!ParseExpression()) + return false; return Parse('E'); case 'L': - ++read_ptr; + ++m_read_ptr; return ParseExpressionPrimary(); default: return ParseType(); } } - + // ::= I * E // extension, the abi says + - - bool ParseTemplateArgs(bool record_template_args = false) + + bool + ParseTemplateArgs(bool record_template_args = false) { - if (record_template_args) ResetTemplateArgs(); - + if (record_template_args) + ResetTemplateArgs(); + bool first_arg = true; - while (*read_ptr != 'E') + while (*m_read_ptr != 'E') { - if (first_arg) first_arg = false; + if (first_arg) + first_arg = false; else WriteCommaSpace(); - + int template_start_cookie = GetStartCookie(); - if (!ParseTemplateArg()) return false; - if (record_template_args) EndTemplateArg(template_start_cookie); + if (!ParseTemplateArg()) + return false; + if (record_template_args) + EndTemplateArg(template_start_cookie); } - ++read_ptr; + ++m_read_ptr; return true; } - + // ::= N [] [] E // ::= N [] [] E // @@ -1756,8 +1898,9 @@ private: // ::= // ::= // ::= - - bool ParseNestedName(NameState & name_state, bool parse_discriminator = false) + + bool + ParseNestedName(NameState & name_state, bool parse_discriminator = false) { int qualifiers = TryParseQualifiers(true, true); bool first_part = true; @@ -1765,30 +1908,33 @@ private: int name_start_cookie = GetStartCookie(); while (true) { - char next = *read_ptr; + char next = *m_read_ptr; if (next == 'E') { - ++read_ptr; + ++m_read_ptr; break; } - + // Record a substitution candidate for all prefixes, but not the full name - if (suppress_substitution) suppress_substitution = false; + if (suppress_substitution) + suppress_substitution = false; else EndSubstitution(name_start_cookie); - + if (next == 'I') { - ++read_ptr; + ++m_read_ptr; name_state.is_last_generic = true; WriteTemplateStart(); - if (!ParseTemplateArgs(name_state.parse_function_params)) return false; + if (!ParseTemplateArgs(name_state.parse_function_params)) + return false; WriteTemplateEnd(); continue; } - - if (first_part) first_part = false; + + if (first_part) + first_part = false; else WriteNamespaceSeparator(); - + name_state.is_last_generic = false; switch (next) { @@ -1804,34 +1950,39 @@ private: case '9': { int name_start_cookie = GetStartCookie(); - if (!ParseSourceName()) return false; + if (!ParseSourceName()) + return false; name_state.last_name_range = EndRange(name_start_cookie); continue; } case 'S': - if (*++read_ptr == 't') + if (*++m_read_ptr == 't') { WriteStdPrefix(); - ++read_ptr; - if (!ParseUnqualifiedName(name_state)) return false; + ++m_read_ptr; + if (!ParseUnqualifiedName(name_state)) + return false; } else { - if (!ParseSubstitution()) return false; + if (!ParseSubstitution()) + return false; suppress_substitution = true; } continue; case 'T': - ++read_ptr; - if (!ParseTemplateParam()) return false; + ++m_read_ptr; + if (!ParseTemplateParam()) + return false; continue; case 'C': - ++read_ptr; - if (!ParseCtor(name_state)) return false; + ++m_read_ptr; + if (!ParseCtor(name_state)) + return false; continue; case 'D': { - switch (*(read_ptr + 1)) + switch (*(m_read_ptr + 1)) { case 't': case 'T': @@ -1840,109 +1991,135 @@ private: #endif return false; } - ++read_ptr; - if (!ParseDtor(name_state)) return false; + ++m_read_ptr; + if (!ParseDtor(name_state)) + return false; continue; } case 'U': - ++read_ptr; - if (!ParseUnnamedTypeName(name_state)) return false; + ++m_read_ptr; + if (!ParseUnnamedTypeName(name_state)) + return false; continue; case 'L': - ++read_ptr; - if (!ParseUnqualifiedName(name_state)) return false; + ++m_read_ptr; + if (!ParseUnqualifiedName(name_state)) + return false; continue; default: - if (!ParseOperatorName(name_state)) return false; + if (!ParseOperatorName(name_state)) + return false; } } - - if (parse_discriminator) TryParseDiscriminator(); - if (name_state.parse_function_params && - !ParseFunctionArgs(name_state, name_start_cookie)) return false; - if (qualifiers) WriteQualifiers(qualifiers); + + if (parse_discriminator) + TryParseDiscriminator(); + if (name_state.parse_function_params + && !ParseFunctionArgs(name_state, name_start_cookie)) + { + return false; + } + if (qualifiers) + WriteQualifiers(qualifiers); return true; } - + // := Z E [] // := Z E s [] // := Z Ed [ ] _ - - bool ParseLocalName(bool parse_function_params) + + bool + ParseLocalName(bool parse_function_params) { - if (!ParseEncoding()) return false; - if (!Parse('E')) return false; - - switch (*read_ptr) + if (!ParseEncoding()) + return false; + if (!Parse('E')) + return false; + + switch (*m_read_ptr) { case 's': + ++m_read_ptr; TryParseDiscriminator(); // Optional and ignored WRITE("::string literal"); break; case 'd': + ++m_read_ptr; TryParseNumber(); // Optional and ignored + if (!Parse('_')) + return false; WriteNamespaceSeparator(); - if (!ParseName()) return false; + if (!ParseName()) + return false; break; default: WriteNamespaceSeparator(); - if (!ParseName(parse_function_params, true)) return false; + if (!ParseName(parse_function_params, true)) + return false; TryParseDiscriminator(); // Optional and ignored } return true; } - + // ::= // ::= // ::= // ::= - + // ::= // ::= - - bool ParseName(bool parse_function_params = false, + + bool + ParseName(bool parse_function_params = false, bool parse_discriminator = false) { - NameState name_state = { parse_function_params }; + NameState name_state = { parse_function_params, false, false, {0, 0}}; int name_start_cookie = GetStartCookie(); - - switch (*read_ptr) + + switch (*m_read_ptr) { case 'N': - ++read_ptr; + ++m_read_ptr; return ParseNestedName(name_state, parse_discriminator); case 'Z': { - ++read_ptr; - if (!ParseLocalName(parse_function_params)) return false; + ++m_read_ptr; + if (!ParseLocalName(parse_function_params)) + return false; break; } case 'L': - ++read_ptr; + ++m_read_ptr; // fallthrough default: { - if (!ParseUnscopedName(name_state)) return false; - - if (*read_ptr == 'I') + if (!ParseUnscopedName(name_state)) + return false; + + if (*m_read_ptr == 'I') { EndSubstitution(name_start_cookie); - - ++read_ptr; + + ++m_read_ptr; name_state.is_last_generic = true; WriteTemplateStart(); - if (!ParseTemplateArgs(parse_function_params)) return false; + if (!ParseTemplateArgs(parse_function_params)) + return false; WriteTemplateEnd(); } break; } } - if (parse_discriminator) TryParseDiscriminator(); + if (parse_discriminator) + TryParseDiscriminator(); if (parse_function_params && - !ParseFunctionArgs(name_state, name_start_cookie)) return false; + !ParseFunctionArgs(name_state, name_start_cookie)) + { + return false; + } return true; } - + // ::= h _ // ::= v _ // @@ -1951,20 +2128,27 @@ private: // // ::= _ // # virtual base override, with vcall offset - - bool ParseCallOffset() + + bool + ParseCallOffset() { - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'h': - if (*read_ptr == 'n') ++read_ptr; - if (TryParseNumber() == -1 || *read_ptr++ != '_') break; + if (*m_read_ptr == 'n') + ++m_read_ptr; + if (TryParseNumber() == -1 || *m_read_ptr++ != '_') + break; return true; case 'v': - if (*read_ptr == 'n') ++read_ptr; - if (TryParseNumber() == -1 || *read_ptr++ != '_') break; - if (*read_ptr == 'n') ++read_ptr; - if (TryParseNumber() == -1 || *read_ptr++ != '_') break; + if (*m_read_ptr == 'n') + ++m_read_ptr; + if (TryParseNumber() == -1 || *m_read_ptr++ != '_') + break; + if (*m_read_ptr == 'n') + ++m_read_ptr; + if (TryParseNumber() == -1 || *m_read_ptr++ != '_') + break; return true; } #ifdef DEBUG_FAILURES @@ -1972,7 +2156,7 @@ private: #endif return false; } - + // ::= TV # virtual table // ::= TT # VTT structure (construction vtable index) // ::= TI # typeinfo structure @@ -1984,10 +2168,11 @@ private: // ::= T // # base is the nominal target function of thunk // extension ::= TC _ # construction vtable for second-in-first - - bool ParseSpecialNameT() + + bool + ParseSpecialNameT() { - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'V': WRITE("vtable for "); @@ -2004,11 +2189,11 @@ private: case 'c': case 'C': #ifdef DEBUG_FAILURES - printf("*** Unsupported thunk or construction vtable name: %.3s\n", read_ptr - 1); + printf("*** Unsupported thunk or construction vtable name: %.3s\n", m_read_ptr - 1); #endif return false; default: - if (*--read_ptr == 'v') + if (*--m_read_ptr == 'v') { WRITE("virtual thunk to "); } @@ -2016,26 +2201,30 @@ private: { WRITE("non-virtual thunk to "); } - if (!ParseCallOffset()) return false; + if (!ParseCallOffset()) + return false; return ParseEncoding(); } } - + // ::= GV # Guard variable for one-time initialization // # No // extension ::= GR # reference temporary for object - - bool ParseSpecialNameG() + + bool + ParseSpecialNameG() { - switch (*read_ptr++) + switch (*m_read_ptr++) { case 'V': WRITE("guard variable for "); - if (!ParseName(true)) return false; + if (!ParseName(true)) + return false; break; case 'R': WRITE("reference temporary for "); - if (!ParseName(true)) return false; + if (!ParseName(true)) + return false; break; default: #ifdef DEBUG_FAILURES @@ -2045,58 +2234,64 @@ private: } return true; } - + // ::= + # types are possible return type, then parameter types - - bool ParseFunctionArgs(NameState & name_state, int return_insert_cookie) + + bool + ParseFunctionArgs(NameState & name_state, int return_insert_cookie) { - char next = *read_ptr; - if (next == 'E' || next == '\0' || next == '.') return true; - + char next = *m_read_ptr; + if (next == 'E' || next == '\0' || next == '.') + return true; + // Clang has a bad habit of making unique manglings by just sticking numbers on the end of a symbol, // which is ambiguous with malformed source name manglings - const char * before_clang_uniquing_test = read_ptr; + const char *before_clang_uniquing_test = m_read_ptr; if (TryParseNumber()) { - if (*read_ptr == '\0') return true; - read_ptr = before_clang_uniquing_test; + if (*m_read_ptr == '\0') + return true; + m_read_ptr = before_clang_uniquing_test; } - + if (name_state.is_last_generic && !name_state.has_no_return_type) { int return_type_start_cookie = GetStartCookie(); - if (!ParseType()) return false; + if (!ParseType()) + return false; Write(' '); ReorderRange(EndRange(return_type_start_cookie), return_insert_cookie); } - + Write('('); bool first_param = true; while (true) { - switch (*read_ptr) + switch (*m_read_ptr) { case '\0': case 'E': case '.': break; case 'v': - ++read_ptr; + ++m_read_ptr; continue; case '_': // Not a formal part of the mangling specification, but clang emits suffixes starting with _block_invoke - if (strncmp(read_ptr, "_block_invoke", 13) == 0) + if (strncmp(m_read_ptr, "_block_invoke", 13) == 0) { - read_ptr += strlen(read_ptr); + m_read_ptr += strlen(m_read_ptr); break; } // fallthrough default: - if (first_param) first_param = false; + if (first_param) + first_param = false; else WriteCommaSpace(); - - if (!ParseType()) return false; + + if (!ParseType()) + return false; continue; } break; @@ -2104,53 +2299,60 @@ private: Write(')'); return true; } - + // ::= // ::= // ::= - - bool ParseEncoding() + + bool + ParseEncoding() { - switch (*read_ptr) + switch (*m_read_ptr) { case 'T': - ++read_ptr; - if (!ParseSpecialNameT()) return false; + ++m_read_ptr; + if (!ParseSpecialNameT()) + return false; break; case 'G': - ++read_ptr; - if (!ParseSpecialNameG()) return false; + ++m_read_ptr; + if (!ParseSpecialNameG()) + return false; break; default: - if (!ParseName(true)) return false; + if (!ParseName(true)) + return false; break; } return true; } - - bool ParseMangling(const char * mangled_name, long mangled_name_length = 0) - { - if (!mangled_name_length) mangled_name_length = strlen(mangled_name); - read_end = mangled_name + mangled_name_length; - read_ptr = mangled_name; - write_ptr = buffer; - next_substitute_index = 0; - next_template_arg_index = rewrite_ranges_size - 1; - - if (*read_ptr++ != '_' || *read_ptr++ != 'Z') + + bool + ParseMangling(const char *mangled_name, long mangled_name_length = 0) + { + if (!mangled_name_length) + mangled_name_length = strlen(mangled_name); + m_read_end = mangled_name + mangled_name_length; + m_read_ptr = mangled_name; + m_write_ptr = m_buffer; + m_next_substitute_index = 0; + m_next_template_arg_index = m_rewrite_ranges_size - 1; + + if (*m_read_ptr++ != '_' || *m_read_ptr++ != 'Z') { #ifdef DEBUG_FAILURES printf("*** Missing _Z prefix\n"); #endif return false; } - if (!ParseEncoding()) return false; - switch (*read_ptr) + if (!ParseEncoding()) + return false; + switch (*m_read_ptr) { case '.': Write(' '); Write('('); - Write(read_ptr, read_end - read_ptr); + Write(m_read_ptr, m_read_end - m_read_ptr); Write(')'); case '\0': return true; @@ -2161,25 +2363,25 @@ private: return false; } } - + private: - + // External scratch storage used during demanglings - - char * buffer; - const char * buffer_end; - BufferRange * rewrite_ranges; - int rewrite_ranges_size; - bool owns_buffer; - bool owns_rewrite_ranges; - + + char *m_buffer; + const char *m_buffer_end; + BufferRange *m_rewrite_ranges; + int m_rewrite_ranges_size; + bool m_owns_buffer; + bool m_owns_m_rewrite_ranges; + // Internal state used during demangling - - const char * read_ptr; - const char * read_end; - char * write_ptr; - int next_template_arg_index; - int next_substitute_index; + + const char *m_read_ptr; + const char *m_read_end; + char *m_write_ptr; + int m_next_template_arg_index; + int m_next_substitute_index; }; } // Anonymous namespace @@ -2187,17 +2389,19 @@ private: // Public entry points referenced from Mangled.cpp namespace lldb_private { - char * FastDemangle(const char* mangled_name) + char * + FastDemangle(const char *mangled_name) { char buffer[16384]; - SymbolDemangler demangler(buffer, sizeof(buffer)); + SymbolDemangler demangler(buffer, sizeof (buffer)); return demangler.GetDemangledCopy(mangled_name); } - char * FastDemangle(const char* mangled_name, long mangled_name_length) + char * + FastDemangle(const char *mangled_name, long mangled_name_length) { char buffer[16384]; - SymbolDemangler demangler(buffer, sizeof(buffer)); + SymbolDemangler demangler(buffer, sizeof (buffer)); return demangler.GetDemangledCopy(mangled_name, mangled_name_length); } } // lldb_private namespace diff --git a/source/Core/FileSpecList.cpp b/source/Core/FileSpecList.cpp index 0cec8faa6bc4..4b1c991c6be4 100644 --- a/source/Core/FileSpecList.cpp +++ b/source/Core/FileSpecList.cpp @@ -107,7 +107,7 @@ FileSpecList::Dump(Stream *s, const char *separator_cstr) const // it is found, else UINT32_MAX is returned. //------------------------------------------------------------------ size_t -FileSpecList::FindFileIndex (size_t start_idx, const FileSpec &file_spec, bool full) const +FileSpecList::FindFileIndex (size_t start_idx, const FileSpec &file_spec, bool full, bool remove_dots) const { const size_t num_files = m_files.size(); @@ -124,7 +124,7 @@ FileSpecList::FindFileIndex (size_t start_idx, const FileSpec &file_spec, bool f } else { - if (FileSpec::Equal (m_files[idx], file_spec, full)) + if (FileSpec::Equal (m_files[idx], file_spec, full, remove_dots)) return idx; } } diff --git a/source/Core/IOHandler.cpp b/source/Core/IOHandler.cpp index add3ad8c5ba3..21ba965ba212 100644 --- a/source/Core/IOHandler.cpp +++ b/source/Core/IOHandler.cpp @@ -19,7 +19,9 @@ #include "lldb/Core/State.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObjectRegister.h" +#ifndef LLDB_DISABLE_LIBEDIT #include "lldb/Host/Editline.h" +#endif #include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Symbol/Block.h" @@ -36,8 +38,9 @@ using namespace lldb; using namespace lldb_private; -IOHandler::IOHandler (Debugger &debugger) : +IOHandler::IOHandler (Debugger &debugger, IOHandler::Type type) : IOHandler (debugger, + type, StreamFileSP(), // Adopt STDIN from top input reader StreamFileSP(), // Adopt STDOUT from top input reader StreamFileSP(), // Adopt STDERR from top input reader @@ -47,6 +50,7 @@ IOHandler::IOHandler (Debugger &debugger) : IOHandler::IOHandler (Debugger &debugger, + IOHandler::Type type, const lldb::StreamFileSP &input_sp, const lldb::StreamFileSP &output_sp, const lldb::StreamFileSP &error_sp, @@ -55,7 +59,9 @@ IOHandler::IOHandler (Debugger &debugger, m_input_sp (input_sp), m_output_sp (output_sp), m_error_sp (error_sp), + m_popped (false), m_flags (flags), + m_type (type), m_user_data (NULL), m_done (false), m_active (false) @@ -151,13 +157,28 @@ IOHandler::GetIsRealTerminal () return GetInputStreamFile()->GetFile().GetIsRealTerminal(); } +void +IOHandler::SetPopped (bool b) +{ + m_popped.SetValue(b, eBroadcastOnChange); +} + +void +IOHandler::WaitForPop () +{ + m_popped.WaitForValueEqualTo(true); +} + IOHandlerConfirm::IOHandlerConfirm (Debugger &debugger, const char *prompt, bool default_response) : IOHandlerEditline(debugger, + IOHandler::Type::Confirm, NULL, // NULL editline_name means no history loaded/saved - NULL, + NULL, // No prompt + NULL, // No continuation prompt false, // Multi-line + false, // Don't colorize the prompt (i.e. the confirm message.) 0, *this), m_default_response (default_response), @@ -310,83 +331,121 @@ IOHandlerDelegate::IOHandlerComplete (IOHandler &io_handler, IOHandlerEditline::IOHandlerEditline (Debugger &debugger, + IOHandler::Type type, const char *editline_name, // Used for saving history files const char *prompt, + const char *continuation_prompt, bool multi_line, + bool color_prompts, uint32_t line_number_start, IOHandlerDelegate &delegate) : IOHandlerEditline(debugger, + type, StreamFileSP(), // Inherit input from top input reader StreamFileSP(), // Inherit output from top input reader StreamFileSP(), // Inherit error from top input reader 0, // Flags editline_name, // Used for saving history files prompt, + continuation_prompt, multi_line, + color_prompts, line_number_start, delegate) { } IOHandlerEditline::IOHandlerEditline (Debugger &debugger, + IOHandler::Type type, const lldb::StreamFileSP &input_sp, const lldb::StreamFileSP &output_sp, const lldb::StreamFileSP &error_sp, uint32_t flags, const char *editline_name, // Used for saving history files const char *prompt, + const char *continuation_prompt, bool multi_line, + bool color_prompts, uint32_t line_number_start, IOHandlerDelegate &delegate) : - IOHandler (debugger, input_sp, output_sp, error_sp, flags), + IOHandler (debugger, type, input_sp, output_sp, error_sp, flags), +#ifndef LLDB_DISABLE_LIBEDIT m_editline_ap (), +#endif m_delegate (delegate), m_prompt (), + m_continuation_prompt(), + m_current_lines_ptr (NULL), m_base_line_number (line_number_start), - m_multi_line (multi_line) + m_curr_line_idx (UINT32_MAX), + m_multi_line (multi_line), + m_color_prompts (color_prompts), + m_interrupt_exits (true) { SetPrompt(prompt); +#ifndef LLDB_DISABLE_LIBEDIT bool use_editline = false; -#ifndef _MSC_VER use_editline = m_input_sp->GetFile().GetIsRealTerminal(); -#else - // Editline is causing issues on Windows, so use the fallback. - use_editline = false; -#endif if (use_editline) { m_editline_ap.reset(new Editline (editline_name, - prompt ? prompt : "", - multi_line, GetInputFILE (), GetOutputFILE (), - GetErrorFILE ())); - if (m_base_line_number > 0) - m_editline_ap->ShowLineNumbers(true, m_base_line_number); - m_editline_ap->SetLineCompleteCallback (LineCompletedCallback, this); + GetErrorFILE (), + m_color_prompts)); + m_editline_ap->SetIsInputCompleteCallback (IsInputCompleteCallback, this); m_editline_ap->SetAutoCompleteCallback (AutoCompleteCallback, this); + // 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_ap->SetFixIndentationCallback (FixIndentationCallback, this, indent_chars); + } } - +#endif + SetBaseLineNumber (m_base_line_number); + SetPrompt(prompt ? prompt : ""); + SetContinuationPrompt(continuation_prompt); } IOHandlerEditline::~IOHandlerEditline () { +#ifndef LLDB_DISABLE_LIBEDIT m_editline_ap.reset(); +#endif +} + +void +IOHandlerEditline::Activate () +{ + IOHandler::Activate(); + m_delegate.IOHandlerActivated(*this); +} + +void +IOHandlerEditline::Deactivate () +{ + IOHandler::Deactivate(); + m_delegate.IOHandlerDeactivated(*this); } bool IOHandlerEditline::GetLine (std::string &line, bool &interrupted) { +#ifndef LLDB_DISABLE_LIBEDIT if (m_editline_ap) { - return m_editline_ap->GetLine(line, interrupted).Success(); + return m_editline_ap->GetLine (line, interrupted); } else { +#endif line.clear(); FILE *in = GetInputFILE(); @@ -394,7 +453,14 @@ IOHandlerEditline::GetLine (std::string &line, bool &interrupted) { if (GetIsInteractive()) { - const char *prompt = GetPrompt(); + const char *prompt = NULL; + + if (m_multi_line && m_curr_line_idx > 0) + prompt = GetContinuationPrompt(); + + if (prompt == NULL) + prompt = GetPrompt(); + if (prompt && prompt[0]) { FILE *out = GetOutputFILE(); @@ -452,19 +518,30 @@ IOHandlerEditline::GetLine (std::string &line, bool &interrupted) SetIsDone(true); } return false; +#ifndef LLDB_DISABLE_LIBEDIT } +#endif } -LineStatus -IOHandlerEditline::LineCompletedCallback (Editline *editline, +#ifndef LLDB_DISABLE_LIBEDIT +bool +IOHandlerEditline::IsInputCompleteCallback (Editline *editline, StringList &lines, - uint32_t line_idx, - Error &error, void *baton) { IOHandlerEditline *editline_reader = (IOHandlerEditline *) baton; - return editline_reader->m_delegate.IOHandlerLinesUpdated(*editline_reader, lines, line_idx, error); + return editline_reader->m_delegate.IOHandlerIsInputComplete(*editline_reader, 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 @@ -487,14 +564,24 @@ IOHandlerEditline::AutoCompleteCallback (const char *current_line, matches); return 0; } +#endif const char * IOHandlerEditline::GetPrompt () { +#ifndef LLDB_DISABLE_LIBEDIT if (m_editline_ap) + { return m_editline_ap->GetPrompt (); - else if (m_prompt.empty()) - return NULL; + } + else + { +#endif + if (m_prompt.empty()) + return NULL; +#ifndef LLDB_DISABLE_LIBEDIT + } +#endif return m_prompt.c_str(); } @@ -505,34 +592,71 @@ IOHandlerEditline::SetPrompt (const char *p) m_prompt = p; else m_prompt.clear(); +#ifndef LLDB_DISABLE_LIBEDIT if (m_editline_ap) m_editline_ap->SetPrompt (m_prompt.empty() ? NULL : m_prompt.c_str()); +#endif return true; } +const char * +IOHandlerEditline::GetContinuationPrompt () +{ + if (m_continuation_prompt.empty()) + return NULL; + return m_continuation_prompt.c_str(); +} + + +void +IOHandlerEditline::SetContinuationPrompt (const char *p) +{ + if (p && p[0]) + m_continuation_prompt = p; + else + m_continuation_prompt.clear(); + +#ifndef LLDB_DISABLE_LIBEDIT + if (m_editline_ap) + m_editline_ap->SetContinuationPrompt (m_continuation_prompt.empty() ? NULL : m_continuation_prompt.c_str()); +#endif +} + + void IOHandlerEditline::SetBaseLineNumber (uint32_t line) { m_base_line_number = line; +} + +uint32_t +IOHandlerEditline::GetCurrentLineIndex () const +{ +#ifndef LLDB_DISABLE_LIBEDIT if (m_editline_ap) - m_editline_ap->ShowLineNumbers (true, line); - + return m_editline_ap->GetCurrentLine(); +#endif + return m_curr_line_idx; } + bool IOHandlerEditline::GetLines (StringList &lines, bool &interrupted) { + m_current_lines_ptr = &lines; + bool success = false; +#ifndef LLDB_DISABLE_LIBEDIT if (m_editline_ap) { - std::string end_token; - success = m_editline_ap->GetLines(end_token, lines, interrupted).Success(); + return m_editline_ap->GetLines (m_base_line_number, lines, interrupted); } else { - LineStatus lines_status = LineStatus::Success; +#endif + bool done = false; Error error; - while (lines_status == LineStatus::Success) + while (!done) { // Show line numbers if we are asked to std::string line; @@ -543,31 +667,23 @@ IOHandlerEditline::GetLines (StringList &lines, bool &interrupted) ::fprintf(out, "%u%s", m_base_line_number + (uint32_t)lines.GetSize(), GetPrompt() == NULL ? " " : ""); } + m_curr_line_idx = lines.GetSize(); + bool interrupted = false; - if (GetLine(line, interrupted)) + if (GetLine(line, interrupted) && !interrupted) { - if (interrupted) - { - lines_status = LineStatus::Done; - } - else - { - lines.AppendString(line); - lines_status = m_delegate.IOHandlerLinesUpdated(*this, lines, lines.GetSize() - 1, error); - } + lines.AppendString(line); + done = m_delegate.IOHandlerIsInputComplete(*this, lines); } else { - lines_status = LineStatus::Done; + done = true; } } - - // Call the IOHandlerLinesUpdated function with UINT32_MAX as the line - // number to indicate all lines are complete - m_delegate.IOHandlerLinesUpdated(*this, lines, UINT32_MAX, error); - success = lines.GetSize() > 0; +#ifndef LLDB_DISABLE_LIBEDIT } +#endif return success; } @@ -588,12 +704,14 @@ IOHandlerEditline::Run () { if (interrupted) { - m_done = true; + m_done = m_interrupt_exits; + m_delegate.IOHandlerInputInterrupted (*this, line); + } else { line = lines.CopyList(); - m_delegate.IOHandlerInputComplete(*this, line); + m_delegate.IOHandlerInputComplete (*this, line); } } else @@ -605,8 +723,10 @@ IOHandlerEditline::Run () { if (GetLine(line, interrupted)) { - if (!interrupted) - m_delegate.IOHandlerInputComplete(*this, line); + if (interrupted) + m_delegate.IOHandlerInputInterrupted (*this, line); + else + m_delegate.IOHandlerInputComplete (*this, line); } else { @@ -619,20 +739,24 @@ IOHandlerEditline::Run () void IOHandlerEditline::Hide () { +#ifndef LLDB_DISABLE_LIBEDIT if (m_editline_ap) m_editline_ap->Hide(); +#endif } void IOHandlerEditline::Refresh () { +#ifndef LLDB_DISABLE_LIBEDIT if (m_editline_ap) { m_editline_ap->Refresh(); } else { +#endif const char *prompt = GetPrompt(); if (prompt && prompt[0]) { @@ -643,14 +767,18 @@ IOHandlerEditline::Refresh () ::fflush(out); } } +#ifndef LLDB_DISABLE_LIBEDIT } +#endif } void IOHandlerEditline::Cancel () { +#ifndef LLDB_DISABLE_LIBEDIT if (m_editline_ap) m_editline_ap->Interrupt (); +#endif } bool @@ -660,16 +788,20 @@ IOHandlerEditline::Interrupt () if (m_delegate.IOHandlerInterrupt(*this)) return true; +#ifndef LLDB_DISABLE_LIBEDIT if (m_editline_ap) return m_editline_ap->Interrupt(); +#endif return false; } void IOHandlerEditline::GotEOF() { +#ifndef LLDB_DISABLE_LIBEDIT if (m_editline_ap) m_editline_ap->Interrupt(); +#endif } // we may want curses to be disabled for some builds @@ -5333,7 +5465,7 @@ protected: DisplayOptions ValueObjectListDelegate::g_options = { true }; IOHandlerCursesGUI::IOHandlerCursesGUI (Debugger &debugger) : - IOHandler (debugger) + IOHandler (debugger, IOHandler::Type::Curses) { } diff --git a/source/Core/Log.cpp b/source/Core/Log.cpp index 3adca6e5385c..d205d363b764 100644 --- a/source/Core/Log.cpp +++ b/source/Core/Log.cpp @@ -26,9 +26,12 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" #include "lldb/Host/Host.h" -#include "lldb/Host/TimeValue.h" #include "lldb/Host/Mutex.h" +#include "lldb/Host/ThisThread.h" +#include "lldb/Host/TimeValue.h" #include "lldb/Interpreter/Args.h" + +#include "llvm/ADT/SmallString.h" using namespace lldb; using namespace lldb_private; @@ -113,7 +116,8 @@ Log::PrintfWithFlagsVarArg (uint32_t flags, const char *format, va_list args) // Add the thread name if requested if (m_options.Test (LLDB_LOG_OPTION_PREPEND_THREAD_NAME)) { - std::string thread_name (Host::GetThreadName (getpid(), Host::GetCurrentThreadID())); + llvm::SmallString<32> thread_name; + ThisThread::GetName(thread_name); if (!thread_name.empty()) header.Printf ("%s ", thread_name.c_str()); } diff --git a/source/Core/Mangled.cpp b/source/Core/Mangled.cpp index c4fa10fedd86..c0ab66cd2880 100644 --- a/source/Core/Mangled.cpp +++ b/source/Core/Mangled.cpp @@ -4986,10 +4986,12 @@ __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status) #include "lldb/Core/RegularExpression.h" #include "lldb/Core/Stream.h" #include "lldb/Core/Timer.h" +#include "lldb/Target/CPPLanguageRuntime.h" #include #include #include + using namespace lldb_private; static inline bool @@ -5000,6 +5002,57 @@ cstring_is_mangled (const char *s) return false; } +static const ConstString & +get_demangled_name_without_arguments (const Mangled *obj) +{ + // This pair is + static std::pair 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; + + ConstString mangled = obj->GetMangledName (); + ConstString demangled = obj->GetDemangledName (); + + 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; + + const char *mangled_name_cstr = mangled.GetCString(); + + if (demangled && mangled_name_cstr && mangled_name_cstr[0]) + { + if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' && + (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure, typeinfo structure, and typeinfo mangled_name + mangled_name_cstr[2] != 'G' && // avoid guard variables + mangled_name_cstr[2] != 'Z')) // named local entities (if we eventually handle eSymbolTypeData, we will want this back) + { + CPPLanguageRuntime::MethodName cxx_method (demangled); + if (!cxx_method.GetBasename().empty() && !cxx_method.GetContext().empty()) + { + std::string shortname = cxx_method.GetContext().str(); + shortname += "::"; + 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; + } + } + } + + if (demangled) + return g_last_demangled; + return g_last_mangled; +} + #pragma mark Mangled //---------------------------------------------------------------------- // Default constructor @@ -5215,6 +5268,14 @@ Mangled::NameMatches (const RegularExpression& regex) const const ConstString& Mangled::GetName (Mangled::NamePreference preference) const { + if (preference == ePreferDemangledWithoutArguments) + { + // Call the accessor to make sure we get a demangled name in case + // it hasn't been demangled yet... + GetDemangledName(); + + return get_demangled_name_without_arguments (this); + } if (preference == ePreferDemangled) { // Call the accessor to make sure we get a demangled name in case diff --git a/source/Core/Module.cpp b/source/Core/Module.cpp index 6f16ada49824..900eea2e0419 100644 --- a/source/Core/Module.cpp +++ b/source/Core/Module.cpp @@ -1309,6 +1309,10 @@ Module::GetObjectFile() // unknown. m_objfile_sp->GetArchitecture (m_arch); } + else + { + ReportError ("failed to load objfile for %s", GetFileSpec().GetPath().c_str()); + } } } return m_objfile_sp.get(); @@ -1706,8 +1710,9 @@ Module::PrepareForFunctionNameLookup (const ConstString &name, const char *name_cstr = name.GetCString(); lookup_name_type_mask = eFunctionNameTypeNone; match_name_after_lookup = false; - const char *base_name_start = NULL; - const char *base_name_end = NULL; + + llvm::StringRef basename; + llvm::StringRef context; if (name_type_mask & eFunctionNameTypeAuto) { @@ -1721,16 +1726,16 @@ Module::PrepareForFunctionNameLookup (const ConstString &name, lookup_name_type_mask |= eFunctionNameTypeSelector; CPPLanguageRuntime::MethodName cpp_method (name); - llvm::StringRef basename (cpp_method.GetBasename()); + basename = cpp_method.GetBasename(); if (basename.empty()) { - if (CPPLanguageRuntime::StripNamespacesFromVariableName (name_cstr, base_name_start, base_name_end)) + if (CPPLanguageRuntime::ExtractContextAndIdentifier (name_cstr, context, basename)) lookup_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); + else + lookup_name_type_mask = eFunctionNameTypeFull; } else { - base_name_start = basename.data(); - base_name_end = base_name_start + basename.size(); lookup_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); } } @@ -1745,9 +1750,7 @@ Module::PrepareForFunctionNameLookup (const ConstString &name, CPPLanguageRuntime::MethodName cpp_method (name); if (cpp_method.IsValid()) { - llvm::StringRef basename (cpp_method.GetBasename()); - base_name_start = basename.data(); - base_name_end = base_name_start + basename.size(); + basename = cpp_method.GetBasename(); if (!cpp_method.GetQualifiers().empty()) { @@ -1760,12 +1763,9 @@ Module::PrepareForFunctionNameLookup (const ConstString &name, } else { - if (!CPPLanguageRuntime::StripNamespacesFromVariableName (name_cstr, base_name_start, base_name_end)) - { - lookup_name_type_mask &= ~(eFunctionNameTypeMethod | eFunctionNameTypeBase); - if (lookup_name_type_mask == eFunctionNameTypeNone) - return; - } + // If the CPP method parser didn't manage to chop this up, try to fill in the base name if we can. + // If a::b::c is passed in, we need to just look up "c", and then we'll filter the result later. + CPPLanguageRuntime::ExtractContextAndIdentifier (name_cstr, context, basename); } } @@ -1780,16 +1780,13 @@ Module::PrepareForFunctionNameLookup (const ConstString &name, } } - if (base_name_start && - base_name_end && - base_name_start != name_cstr && - base_name_start < base_name_end) + if (!basename.empty()) { // The name supplied was a partial C++ path like "a::count". In this case we want to do a // lookup on the basename "count" and then make sure any matching results contain "a::count" // so that it would match "b::a::count" and "a::count". This is why we set "match_name_after_lookup" // to true - lookup_name.SetCStringWithLength(base_name_start, base_name_end - base_name_start); + lookup_name.SetString(basename); match_name_after_lookup = true; } else diff --git a/source/Core/ModuleList.cpp b/source/Core/ModuleList.cpp index 156f3cf9d0aa..879eb9bd1822 100644 --- a/source/Core/ModuleList.cpp +++ b/source/Core/ModuleList.cpp @@ -484,6 +484,26 @@ ModuleList::FindFunctionSymbols (const ConstString &name, return sc_list.GetSize() - old_size; } + +size_t +ModuleList::FindFunctions(const RegularExpression &name, + bool include_symbols, + bool include_inlines, + bool append, + SymbolContextList& sc_list) +{ + const size_t old_size = sc_list.GetSize(); + + Mutex::Locker locker(m_modules_mutex); + collection::const_iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) + { + (*pos)->FindFunctions (name, include_symbols, include_inlines, append, sc_list); + } + + return sc_list.GetSize() - old_size; +} + size_t ModuleList::FindCompileUnits (const FileSpec &path, bool append, diff --git a/source/Core/PluginManager.cpp b/source/Core/PluginManager.cpp index cda55802fab8..95574cb2deaf 100644 --- a/source/Core/PluginManager.cpp +++ b/source/Core/PluginManager.cpp @@ -2068,6 +2068,229 @@ PluginManager::GetUnwindAssemblyCreateCallbackForPluginName (const ConstString & return NULL; } +#pragma mark MemoryHistory + +struct MemoryHistoryInstance +{ + MemoryHistoryInstance() : + name(), + description(), + create_callback(NULL) + { + } + + ConstString name; + std::string description; + MemoryHistoryCreateInstance create_callback; +}; + +typedef std::vector MemoryHistoryInstances; + +static Mutex & +GetMemoryHistoryMutex () +{ + static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); + return g_instances_mutex; +} + +static MemoryHistoryInstances & +GetMemoryHistoryInstances () +{ + static MemoryHistoryInstances g_instances; + return g_instances; +} + +bool +PluginManager::RegisterPlugin +( + const ConstString &name, + const char *description, + MemoryHistoryCreateInstance create_callback + ) +{ + if (create_callback) + { + MemoryHistoryInstance instance; + assert ((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + Mutex::Locker locker (GetMemoryHistoryMutex ()); + GetMemoryHistoryInstances ().push_back (instance); + } + return false; +} + +bool +PluginManager::UnregisterPlugin (MemoryHistoryCreateInstance create_callback) +{ + if (create_callback) + { + Mutex::Locker locker (GetMemoryHistoryMutex ()); + MemoryHistoryInstances &instances = GetMemoryHistoryInstances (); + + MemoryHistoryInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++ pos) + { + if (pos->create_callback == create_callback) + { + instances.erase(pos); + return true; + } + } + } + return false; +} + +MemoryHistoryCreateInstance +PluginManager::GetMemoryHistoryCreateCallbackAtIndex (uint32_t idx) +{ + Mutex::Locker locker (GetMemoryHistoryMutex ()); + MemoryHistoryInstances &instances = GetMemoryHistoryInstances (); + if (idx < instances.size()) + return instances[idx].create_callback; + return NULL; +} + + +MemoryHistoryCreateInstance +PluginManager::GetMemoryHistoryCreateCallbackForPluginName (const ConstString &name) +{ + if (name) + { + Mutex::Locker locker (GetMemoryHistoryMutex ()); + MemoryHistoryInstances &instances = GetMemoryHistoryInstances (); + + MemoryHistoryInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++ pos) + { + if (name == pos->name) + return pos->create_callback; + } + } + return NULL; +} + +#pragma mark InstrumentationRuntime + +struct InstrumentationRuntimeInstance +{ + InstrumentationRuntimeInstance() : + name(), + description(), + create_callback(NULL) + { + } + + ConstString name; + std::string description; + InstrumentationRuntimeCreateInstance create_callback; + InstrumentationRuntimeGetType get_type_callback; +}; + +typedef std::vector InstrumentationRuntimeInstances; + +static Mutex & +GetInstrumentationRuntimeMutex () +{ + static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); + return g_instances_mutex; +} + +static InstrumentationRuntimeInstances & +GetInstrumentationRuntimeInstances () +{ + static InstrumentationRuntimeInstances g_instances; + return g_instances; +} + +bool +PluginManager::RegisterPlugin +( + const ConstString &name, + const char *description, + InstrumentationRuntimeCreateInstance create_callback, + InstrumentationRuntimeGetType get_type_callback + ) +{ + if (create_callback) + { + InstrumentationRuntimeInstance instance; + assert ((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.get_type_callback = get_type_callback; + Mutex::Locker locker (GetInstrumentationRuntimeMutex ()); + GetInstrumentationRuntimeInstances ().push_back (instance); + } + return false; +} + +bool +PluginManager::UnregisterPlugin (InstrumentationRuntimeCreateInstance create_callback) +{ + if (create_callback) + { + Mutex::Locker locker (GetInstrumentationRuntimeMutex ()); + InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances (); + + InstrumentationRuntimeInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++ pos) + { + if (pos->create_callback == create_callback) + { + instances.erase(pos); + return true; + } + } + } + return false; +} + +InstrumentationRuntimeGetType +PluginManager::GetInstrumentationRuntimeGetTypeCallbackAtIndex (uint32_t idx) +{ + Mutex::Locker locker (GetInstrumentationRuntimeMutex ()); + InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances (); + if (idx < instances.size()) + return instances[idx].get_type_callback; + return NULL; +} + +InstrumentationRuntimeCreateInstance +PluginManager::GetInstrumentationRuntimeCreateCallbackAtIndex (uint32_t idx) +{ + Mutex::Locker locker (GetInstrumentationRuntimeMutex ()); + InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances (); + if (idx < instances.size()) + return instances[idx].create_callback; + return NULL; +} + + +InstrumentationRuntimeCreateInstance +PluginManager::GetInstrumentationRuntimeCreateCallbackForPluginName (const ConstString &name) +{ + if (name) + { + Mutex::Locker locker (GetInstrumentationRuntimeMutex ()); + InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances (); + + InstrumentationRuntimeInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++ pos) + { + if (name == pos->name) + return pos->create_callback; + } + } + return NULL; +} + +#pragma mark PluginManager + void PluginManager::DebuggerInitialize (Debugger &debugger) { diff --git a/source/Core/RegularExpression.cpp b/source/Core/RegularExpression.cpp index 88415f616828..54924d069537 100644 --- a/source/Core/RegularExpression.cpp +++ b/source/Core/RegularExpression.cpp @@ -162,20 +162,11 @@ RegularExpression::Execute(const char* s, Match *match, int execute_flags) const bool RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, std::string& match_str) const { - if (idx < m_matches.size()) + llvm::StringRef match_str_ref; + if (GetMatchAtIndex(s, idx, match_str_ref)) { - if (m_matches[idx].rm_eo == m_matches[idx].rm_so) - { - // Matched the empty string... - match_str.clear(); - return true; - } - else if (m_matches[idx].rm_eo > m_matches[idx].rm_so) - { - match_str.assign (s + m_matches[idx].rm_so, - m_matches[idx].rm_eo - m_matches[idx].rm_so); - return true; - } + match_str = std::move(match_str_ref.str()); + return true; } return false; } @@ -185,6 +176,9 @@ RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, llvm::St { if (idx < m_matches.size()) { + if (m_matches[idx].rm_eo == -1 && m_matches[idx].rm_so == -1) + return false; + if (m_matches[idx].rm_eo == m_matches[idx].rm_so) { // Matched the empty string... diff --git a/source/Core/SearchFilter.cpp b/source/Core/SearchFilter.cpp index dee2f2e4bd5e..9c3412a422d0 100644 --- a/source/Core/SearchFilter.cpp +++ b/source/Core/SearchFilter.cpp @@ -119,6 +119,15 @@ SearchFilter::Dump (Stream *s) const } +lldb::SearchFilterSP +SearchFilter::CopyForBreakpoint (Breakpoint &breakpoint) +{ + SearchFilterSP ret_sp = DoCopyForBreakpoint (breakpoint); + TargetSP target_sp = breakpoint.GetTargetSP(); + ret_sp->SetTarget(target_sp); + return ret_sp; +} + //---------------------------------------------------------------------- // UTILITY Functions to help iterate down through the elements of the // SymbolContext. @@ -281,29 +290,36 @@ SearchFilter::DoFunctionIteration (Function *function, const SymbolContext &cont } //---------------------------------------------------------------------- -// SearchFilterForNonModuleSpecificSearches: +// SearchFilterForUnconstrainedSearches: // Selects a shared library matching a given file spec, consulting the targets "black list". //---------------------------------------------------------------------- - bool - SearchFilterForNonModuleSpecificSearches::ModulePasses (const FileSpec &module_spec) - { - if (m_target_sp->ModuleIsExcludedForNonModuleSpecificSearches (module_spec)) - return false; - else - return true; - } - - bool - SearchFilterForNonModuleSpecificSearches::ModulePasses (const lldb::ModuleSP &module_sp) - { - if (!module_sp) - return true; - else if (m_target_sp->ModuleIsExcludedForNonModuleSpecificSearches (module_sp)) - return false; - else - return true; - } +bool +SearchFilterForUnconstrainedSearches::ModulePasses (const FileSpec &module_spec) +{ + if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches (module_spec)) + return false; + else + return true; +} + +bool +SearchFilterForUnconstrainedSearches::ModulePasses (const lldb::ModuleSP &module_sp) +{ + if (!module_sp) + return true; + else if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches (module_sp)) + return false; + else + return true; +} + +lldb::SearchFilterSP +SearchFilterForUnconstrainedSearches::DoCopyForBreakpoint (Breakpoint &breakpoint) +{ + SearchFilterSP ret_sp(new SearchFilterForUnconstrainedSearches(*this)); + return ret_sp; +} //---------------------------------------------------------------------- // SearchFilterByModule: @@ -434,7 +450,7 @@ SearchFilterByModule::GetDescription (Stream *s) } else { - s->PutCString(m_module_spec.GetFilename().AsCString("")); + s->PutCString(m_module_spec.GetFilename().AsCString("")); } } @@ -449,6 +465,14 @@ SearchFilterByModule::Dump (Stream *s) const { } + +lldb::SearchFilterSP +SearchFilterByModule::DoCopyForBreakpoint (Breakpoint &breakpoint) +{ + SearchFilterSP ret_sp(new SearchFilterByModule(*this)); + return ret_sp; +} + //---------------------------------------------------------------------- // SearchFilterByModuleList: // Selects a shared library matching a given file spec @@ -458,7 +482,8 @@ SearchFilterByModule::Dump (Stream *s) const // SearchFilterByModuleList constructors //---------------------------------------------------------------------- -SearchFilterByModuleList::SearchFilterByModuleList (const lldb::TargetSP &target_sp, const FileSpecList &module_list) : +SearchFilterByModuleList::SearchFilterByModuleList (const lldb::TargetSP &target_sp, + const FileSpecList &module_list) : SearchFilter (target_sp), m_module_spec_list (module_list) { @@ -587,7 +612,7 @@ SearchFilterByModuleList::GetDescription (Stream *s) } else { - s->PutCString(m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString("")); + s->PutCString(m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString("")); } } else @@ -603,7 +628,7 @@ SearchFilterByModuleList::GetDescription (Stream *s) } else { - s->PutCString(m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString("")); + s->PutCString(m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString("")); } if (i != num_modules - 1) s->PutCString (", "); @@ -623,6 +648,14 @@ SearchFilterByModuleList::Dump (Stream *s) const } +lldb::SearchFilterSP +SearchFilterByModuleList::DoCopyForBreakpoint (Breakpoint &breakpoint) +{ + SearchFilterSP ret_sp(new SearchFilterByModuleList(*this)); + return ret_sp; +} + + //---------------------------------------------------------------------- // SearchFilterByModuleListAndCU: // Selects a shared library matching a given file spec @@ -778,7 +811,7 @@ SearchFilterByModuleListAndCU::GetDescription (Stream *s) } else { - s->PutCString(m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString("")); + s->PutCString(m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString("")); } } else if (num_modules > 0) @@ -794,7 +827,7 @@ SearchFilterByModuleListAndCU::GetDescription (Stream *s) } else { - s->PutCString(m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString("")); + s->PutCString(m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString("")); } if (i != num_modules - 1) s->PutCString (", "); @@ -814,3 +847,10 @@ SearchFilterByModuleListAndCU::Dump (Stream *s) const } +lldb::SearchFilterSP +SearchFilterByModuleListAndCU::DoCopyForBreakpoint (Breakpoint &breakpoint) +{ + SearchFilterSP ret_sp(new SearchFilterByModuleListAndCU(*this)); + return ret_sp; +} + diff --git a/source/Core/Section.cpp b/source/Core/Section.cpp index 3267c1866221..ea33a62b775f 100644 --- a/source/Core/Section.cpp +++ b/source/Core/Section.cpp @@ -28,7 +28,8 @@ Section::Section (const ModuleSP &module_sp, lldb::offset_t file_offset, lldb::offset_t file_size, uint32_t log2align, - uint32_t flags) : + uint32_t flags, + uint32_t target_byte_size/*=1*/) : ModuleChild (module_sp), UserID (sect_id), Flags (flags), @@ -44,7 +45,8 @@ Section::Section (const ModuleSP &module_sp, m_children (), m_fake (false), m_encrypted (false), - m_thread_specific (false) + m_thread_specific (false), + m_target_byte_size(target_byte_size) { // printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s\n", // this, module_sp.get(), sect_id, file_addr, file_addr + byte_size, file_offset, file_offset + file_size, flags, name.GetCString()); @@ -61,7 +63,8 @@ Section::Section (const lldb::SectionSP &parent_section_sp, lldb::offset_t file_offset, lldb::offset_t file_size, uint32_t log2align, - uint32_t flags) : + uint32_t flags, + uint32_t target_byte_size/*=1*/) : ModuleChild (module_sp), UserID (sect_id), Flags (flags), @@ -77,7 +80,8 @@ Section::Section (const lldb::SectionSP &parent_section_sp, m_children (), m_fake (false), m_encrypted (false), - m_thread_specific (false) + m_thread_specific (false), + m_target_byte_size(target_byte_size) { // printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s.%s\n", // this, module_sp.get(), sect_id, file_addr, file_addr + byte_size, file_offset, file_offset + file_size, flags, parent_section_sp->GetName().GetCString(), name.GetCString()); @@ -186,7 +190,7 @@ Section::ContainsFileAddress (addr_t vm_addr) const { if (file_addr <= vm_addr) { - const addr_t offset = vm_addr - file_addr; + const addr_t offset = (vm_addr - file_addr) * m_target_byte_size; return offset < GetByteSize(); } } diff --git a/source/Core/StreamString.cpp b/source/Core/StreamString.cpp index 8d7d039fd65c..ef2b70583ebd 100644 --- a/source/Core/StreamString.cpp +++ b/source/Core/StreamString.cpp @@ -65,6 +65,22 @@ StreamString::GetSize () const return m_packet.size(); } +size_t +StreamString::GetSizeOfLastLine () const +{ + const size_t length = m_packet.size(); + size_t last_line_begin_pos = m_packet.find_last_of("\r\n"); + if (last_line_begin_pos == std::string::npos) + { + return length; + } + else + { + ++last_line_begin_pos; + return length - last_line_begin_pos; + } +} + std::string & StreamString::GetString() { diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp index 1819e834536a..fa5fb14db05b 100644 --- a/source/Core/ValueObject.cpp +++ b/source/Core/ValueObject.cpp @@ -34,8 +34,12 @@ #include "lldb/Core/ValueObjectSyntheticFilter.h" #include "lldb/DataFormatters/DataVisualization.h" +#include "lldb/DataFormatters/StringPrinter.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" +#include "lldb/Expression/ClangExpressionVariable.h" +#include "lldb/Expression/ClangPersistentVariables.h" + #include "lldb/Host/Endian.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -43,6 +47,7 @@ #include "lldb/Symbol/ClangASTType.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Type.h" #include "lldb/Target/ExecutionContext.h" @@ -77,6 +82,7 @@ ValueObject::ValueObject (ValueObject &parent) : m_location_str (), m_summary_str (), m_object_desc_str (), + m_validation_result(), m_manager(parent.GetManager()), m_children (), m_synthetic_children (), @@ -89,8 +95,10 @@ ValueObject::ValueObject (ValueObject &parent) : m_type_summary_sp(), m_type_format_sp(), m_synthetic_children_sp(), + m_type_validator_sp(), m_user_id_of_forced_summary(), m_address_type_of_ptr_or_ref_children(eAddressTypeInvalid), + m_value_checksum(), m_value_is_valid (false), m_value_did_change (false), m_children_count_valid (false), @@ -100,7 +108,8 @@ ValueObject::ValueObject (ValueObject &parent) : 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_did_calculate_complete_objc_class_type(false), + m_is_synthetic_children_generated(parent.m_is_synthetic_children_generated) { m_manager->ManageObject(this); } @@ -123,6 +132,7 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope, m_location_str (), m_summary_str (), m_object_desc_str (), + m_validation_result(), m_manager(), m_children (), m_synthetic_children (), @@ -135,8 +145,10 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope, m_type_summary_sp(), m_type_format_sp(), m_synthetic_children_sp(), + m_type_validator_sp(), m_user_id_of_forced_summary(), m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type), + m_value_checksum(), m_value_is_valid (false), m_value_did_change (false), m_children_count_valid (false), @@ -146,7 +158,8 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope, 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_did_calculate_complete_objc_class_type(false), + m_is_synthetic_children_generated(false) { m_manager = new ValueObjectManager(); m_manager->ManageObject (this); @@ -181,7 +194,7 @@ ValueObject::UpdateValueIfNeeded (bool update_format) return m_error.Success(); } - bool first_update = m_update_point.IsFirstEvaluation(); + bool first_update = IsChecksumEmpty(); if (m_update_point.NeedsUpdating()) { @@ -210,10 +223,35 @@ ValueObject::UpdateValueIfNeeded (bool update_format) m_error.Clear(); // Call the pure virtual function to update the value + + bool need_compare_checksums = false; + llvm::SmallVector old_checksum; + + if (!first_update && CanProvideValue()) + { + need_compare_checksums = true; + old_checksum.resize(m_value_checksum.size()); + std::copy(m_value_checksum.begin(), m_value_checksum.end(), old_checksum.begin()); + } + bool success = UpdateValue (); SetValueIsValid (success); + if (success) + { + const uint64_t max_checksum_size = 128; + m_data.Checksum(m_value_checksum, + max_checksum_size); + } + else + { + need_compare_checksums = false; + m_value_checksum.clear(); + } + + assert (!need_compare_checksums || (!old_checksum.empty() && !m_value_checksum.empty())); + if (first_update) SetValueDidChange (false); else if (!m_value_did_change && success == false) @@ -222,6 +260,11 @@ ValueObject::UpdateValueIfNeeded (bool update_format) // as changed if the value used to be valid and now isn't SetValueDidChange (value_was_valid); } + else if (need_compare_checksums) + { + SetValueDidChange(memcmp(&old_checksum[0], &m_value_checksum[0], m_value_checksum.size())); + } + } else { @@ -253,6 +296,7 @@ ValueObject::UpdateFormatsIfNeeded() #ifndef LLDB_DISABLE_PYTHON SetSyntheticChildren(DataVisualization::GetSyntheticChildren (*this, GetDynamicValueType())); #endif + SetValidator(DataVisualization::GetValidator(*this, GetDynamicValueType())); } return any_change; @@ -486,7 +530,6 @@ ValueObject::SetValueIsValid (bool b) bool ValueObject::GetValueDidChange () { - GetValueAsCString (); return m_value_did_change; } @@ -746,9 +789,9 @@ ValueObject::MightHaveChildren() const uint32_t type_info = GetTypeInfo(); if (type_info) { - if (type_info & (ClangASTType::eTypeHasChildren | - ClangASTType::eTypeIsPointer | - ClangASTType::eTypeIsReference)) + if (type_info & (eTypeHasChildren | + eTypeIsPointer | + eTypeIsReference)) has_children = true; } else @@ -834,6 +877,14 @@ ValueObject::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_ bool ValueObject::GetSummaryAsCString (TypeSummaryImpl* summary_ptr, std::string& destination) +{ + return GetSummaryAsCString(summary_ptr, destination, TypeSummaryOptions()); +} + +bool +ValueObject::GetSummaryAsCString (TypeSummaryImpl* summary_ptr, + std::string& destination, + const TypeSummaryOptions& options) { destination.clear(); @@ -851,66 +902,11 @@ ValueObject::GetSummaryAsCString (TypeSummaryImpl* summary_ptr, GetName().GetCString(), summary_ptr->GetDescription().c_str());*/ - if (UpdateValueIfNeeded (false)) + if (UpdateValueIfNeeded (false) && summary_ptr) { - if (summary_ptr) - { - if (HasSyntheticValue()) - m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on the synthetic children being up-to-date (e.g. ${svar%#}) - summary_ptr->FormatObject(this, destination); - } - else - { - ClangASTType clang_type = GetClangType(); - - // Do some default printout for function pointers - if (clang_type) - { - if (clang_type.IsFunctionPointerType ()) - { - StreamString sstr; - AddressType func_ptr_address_type = eAddressTypeInvalid; - addr_t func_ptr_address = GetPointerValue (&func_ptr_address_type); - if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) - { - switch (func_ptr_address_type) - { - case eAddressTypeInvalid: - case eAddressTypeFile: - break; - - case eAddressTypeLoad: - { - ExecutionContext exe_ctx (GetExecutionContextRef()); - - Address so_addr; - Target *target = exe_ctx.GetTargetPtr(); - if (target && target->GetSectionLoadList().IsEmpty() == false) - { - if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr)) - { - so_addr.Dump (&sstr, - exe_ctx.GetBestExecutionContextScope(), - Address::DumpStyleResolvedDescription, - Address::DumpStyleSectionNameOffset); - } - } - } - break; - - case eAddressTypeHost: - break; - } - } - if (sstr.GetSize() > 0) - { - destination.assign (1, '('); - destination.append (sstr.GetData(), sstr.GetSize()); - destination.append (1, ')'); - } - } - } - } + if (HasSyntheticValue()) + m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on the synthetic children being up-to-date (e.g. ${svar%#}) + summary_ptr->FormatObject(this, destination, options); } m_is_getting_summary = false; return !destination.empty(); @@ -922,25 +918,35 @@ ValueObject::GetSummaryAsCString () if (UpdateValueIfNeeded(true) && m_summary_str.empty()) { GetSummaryAsCString(GetSummaryFormat().get(), - m_summary_str); + m_summary_str, + TypeSummaryOptions()); } if (m_summary_str.empty()) return NULL; return m_summary_str.c_str(); } +bool +ValueObject::GetSummaryAsCString (std::string& destination, + const TypeSummaryOptions& options) +{ + return GetSummaryAsCString(GetSummaryFormat().get(), + destination, + options); +} + bool ValueObject::IsCStringContainer(bool check_pointer) { ClangASTType pointee_or_element_clang_type; const Flags type_flags (GetTypeInfo (&pointee_or_element_clang_type)); - bool is_char_arr_ptr (type_flags.AnySet (ClangASTType::eTypeIsArray | ClangASTType::eTypeIsPointer) && + bool is_char_arr_ptr (type_flags.AnySet (eTypeIsArray | eTypeIsPointer) && pointee_or_element_clang_type.IsCharType ()); if (!is_char_arr_ptr) return false; if (!check_pointer) return true; - if (type_flags.Test(ClangASTType::eTypeIsArray)) + if (type_flags.Test(eTypeIsArray)) return true; addr_t cstr_address = LLDB_INVALID_ADDRESS; AddressType cstr_address_type = eAddressTypeInvalid; @@ -955,8 +961,8 @@ ValueObject::GetPointeeData (DataExtractor& data, { ClangASTType pointee_or_element_clang_type; const uint32_t type_info = GetTypeInfo (&pointee_or_element_clang_type); - const bool is_pointer_type = type_info & ClangASTType::eTypeIsPointer; - const bool is_array_type = type_info & ClangASTType::eTypeIsArray; + const bool is_pointer_type = type_info & eTypeIsPointer; + const bool is_array_type = type_info & eTypeIsArray; if (!(is_pointer_type || is_array_type)) return 0; @@ -1182,20 +1188,31 @@ strlen_or_inf (const char* str, return len; } +static bool +CopyStringDataToBufferSP(const StreamString& source, + lldb::DataBufferSP& destination) +{ + destination.reset(new DataBufferHeap(source.GetSize()+1,0)); + memcpy(destination->GetBytes(), source.GetString().c_str(), source.GetSize()); + return true; +} + size_t -ValueObject::ReadPointedString (Stream& s, +ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp, Error& error, uint32_t max_length, bool honor_array, Format item_format) { + StreamString s; ExecutionContext exe_ctx (GetExecutionContextRef()); Target* target = exe_ctx.GetTargetPtr(); - + if (!target) { s << ""; error.SetErrorString("no target to read from"); + CopyStringDataToBufferSP(s, buffer_sp); return 0; } @@ -1208,7 +1225,7 @@ ValueObject::ReadPointedString (Stream& s, ClangASTType clang_type = GetClangType(); ClangASTType elem_or_pointee_clang_type; const Flags type_flags (GetTypeInfo (&elem_or_pointee_clang_type)); - if (type_flags.AnySet (ClangASTType::eTypeIsArray | ClangASTType::eTypeIsPointer) && + if (type_flags.AnySet (eTypeIsArray | eTypeIsPointer) && elem_or_pointee_clang_type.IsCharType ()) { addr_t cstr_address = LLDB_INVALID_ADDRESS; @@ -1216,7 +1233,7 @@ ValueObject::ReadPointedString (Stream& s, size_t cstr_len = 0; bool capped_data = false; - if (type_flags.Test (ClangASTType::eTypeIsArray)) + if (type_flags.Test (eTypeIsArray)) { // We have an array uint64_t array_size = 0; @@ -1241,9 +1258,10 @@ ValueObject::ReadPointedString (Stream& s, { s << ""; error.SetErrorString("invalid address"); + CopyStringDataToBufferSP(s, buffer_sp); return 0; } - + Address cstr_so_addr (cstr_address); DataExtractor data; if (cstr_len > 0 && honor_array) @@ -1251,30 +1269,21 @@ ValueObject::ReadPointedString (Stream& s, // I am using GetPointeeData() here to abstract the fact that some ValueObjects are actually frozen pointers in the host // but the pointed-to data lives in the debuggee, and GetPointeeData() automatically takes care of this GetPointeeData(data, 0, cstr_len); - + if ((bytes_read = data.GetByteSize()) > 0) { total_bytes_read = bytes_read; - s << '"'; - data.Dump (&s, - 0, // Start offset in "data" - item_format, - 1, // Size of item (1 byte for a char!) - bytes_read, // How many bytes to print? - UINT32_MAX, // num per line - LLDB_INVALID_ADDRESS,// base address - 0, // bitfield bit size - 0); // bitfield bit offset + for (size_t offset = 0; offset < bytes_read; offset++) + s.Printf("%c", *data.PeekData(offset, 1)); if (capped_data) s << "..."; - s << '"'; } } else { cstr_len = max_length; const size_t k_max_buf_size = 64; - + size_t offset = 0; int cstr_len_displayed = -1; @@ -1288,12 +1297,10 @@ ValueObject::ReadPointedString (Stream& s, size_t len = strlen_or_inf (cstr, k_max_buf_size, k_max_buf_size+1); if (len > k_max_buf_size) len = k_max_buf_size; - if (cstr && cstr_len_displayed < 0) - s << '"'; - + if (cstr_len_displayed < 0) cstr_len_displayed = len; - + if (len == 0) break; cstr_len_displayed += len; @@ -1302,15 +1309,8 @@ ValueObject::ReadPointedString (Stream& s, if (len > cstr_len) len = cstr_len; - data.Dump (&s, - 0, // Start offset in "data" - item_format, - 1, // Size of item (1 byte for a char!) - len, // How many bytes to print? - UINT32_MAX, // num per line - LLDB_INVALID_ADDRESS,// base address - 0, // bitfield bit size - 0); // bitfield bit offset + for (size_t offset = 0; offset < bytes_read; offset++) + s.Printf("%c", *data.PeekData(offset, 1)); if (len < k_max_buf_size) break; @@ -1320,14 +1320,13 @@ ValueObject::ReadPointedString (Stream& s, capped_cstr = true; break; } - + cstr_len -= len; offset += len; } if (cstr_len_displayed >= 0) { - s << '"'; if (capped_cstr) s << "..."; } @@ -1338,9 +1337,27 @@ ValueObject::ReadPointedString (Stream& s, error.SetErrorString("not a string object"); s << ""; } + CopyStringDataToBufferSP(s, buffer_sp); return total_bytes_read; } +std::pair +ValueObject::GetValidationStatus () +{ + if (!UpdateValueIfNeeded(true)) + return {TypeValidatorResult::Success,""}; // not the validator's job to discuss update problems + + if (m_validation_result.hasValue()) + return m_validation_result.getValue(); + + if (!m_type_validator_sp) + return {TypeValidatorResult::Success,""}; // no validator no failure + + auto outcome = m_type_validator_sp->FormatObject(this); + + return (m_validation_result = {outcome.m_result,outcome.m_message}).getValue(); +} + const char * ValueObject::GetObjectDescription () { @@ -1428,7 +1445,7 @@ ValueObject::GetValueAsCString () } else { - my_format = GetClangType().GetFormat(); + my_format = GetValue().GetClangType().GetFormat(); } } } @@ -1460,7 +1477,7 @@ uint64_t ValueObject::GetValueAsUnsigned (uint64_t fail_value, bool *success) { // If our byte size is zero this is an aggregate type that has children - if (!GetClangType().IsAggregateType()) + if (CanProvideValue()) { Scalar scalar; if (ResolveValue (scalar)) @@ -1481,7 +1498,7 @@ int64_t ValueObject::GetValueAsSigned (int64_t fail_value, bool *success) { // If our byte size is zero this is an aggregate type that has children - if (!GetClangType().IsAggregateType()) + if (CanProvideValue()) { Scalar scalar; if (ResolveValue (scalar)) @@ -1506,7 +1523,7 @@ ValueObject::HasSpecialPrintableRepresentation(ValueObjectRepresentationStyle va Format custom_format) { Flags flags(GetTypeInfo()); - if (flags.AnySet(ClangASTType::eTypeIsArray | ClangASTType::eTypeIsPointer) + if (flags.AnySet(eTypeIsArray | eTypeIsPointer) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) { if (IsCStringContainer(true) && @@ -1516,7 +1533,7 @@ ValueObject::HasSpecialPrintableRepresentation(ValueObjectRepresentationStyle va custom_format == eFormatVectorOfChar)) return true; - if (flags.Test(ClangASTType::eTypeIsArray)) + if (flags.Test(eTypeIsArray)) { if ((custom_format == eFormatBytes) || (custom_format == eFormatBytesWithASCII)) @@ -1555,7 +1572,7 @@ ValueObject::DumpPrintableRepresentation(Stream& s, if (allow_special) { - if (flags.AnySet(ClangASTType::eTypeIsArray | ClangASTType::eTypeIsPointer) + if (flags.AnySet(eTypeIsArray | eTypeIsPointer) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) { // when being asked to get a printable display an array or pointer type directly, @@ -1568,11 +1585,19 @@ ValueObject::DumpPrintableRepresentation(Stream& s, custom_format == eFormatVectorOfChar)) // print char[] & char* directly { Error error; - ReadPointedString(s, + lldb::DataBufferSP buffer_sp; + ReadPointedString(buffer_sp, error, 0, (custom_format == eFormatVectorOfChar) || (custom_format == eFormatCharArray)); + lldb_private::formatters::ReadBufferAndDumpToStreamOptions options(*this); + options.SetData(DataExtractor(buffer_sp, lldb::eByteOrderInvalid, 8)); // none of this matters for a string - pass some defaults + options.SetStream(&s); + options.SetPrefixToken(0); + options.SetQuote('"'); + options.SetSourceSize(buffer_sp->GetByteSize()); + lldb_private::formatters::ReadBufferAndDumpToStream(options); return !error.Fail(); } @@ -1581,7 +1606,7 @@ ValueObject::DumpPrintableRepresentation(Stream& s, // this only works for arrays, because I have no way to know when // the pointed memory ends, and no special \0 end of data marker - if (flags.Test(ClangASTType::eTypeIsArray)) + if (flags.Test(eTypeIsArray)) { if ((custom_format == eFormatBytes) || (custom_format == eFormatBytesWithASCII)) @@ -1729,7 +1754,7 @@ ValueObject::DumpPrintableRepresentation(Stream& s, cstr = GetSummaryAsCString(); else if (val_obj_display == eValueObjectRepresentationStyleSummary) { - if (GetClangType().IsAggregateType()) + if (!CanProvideValue()) { strm.Printf("%s @ %s", GetTypeName().AsCString(), GetLocationAsCString()); cstr = strm.GetString().c_str(); @@ -2037,7 +2062,7 @@ ValueObject::IsPossibleDynamicType () bool ValueObject::IsObjCNil () { - const uint32_t mask = ClangASTType::eTypeIsObjC | ClangASTType::eTypeIsPointer; + const uint32_t mask = eTypeIsObjC | eTypeIsPointer; bool isObjCpointer = (((GetClangType().GetTypeInfo(NULL)) & mask) == mask); if (!isObjCpointer) return false; @@ -2050,10 +2075,10 @@ ValueObjectSP ValueObject::GetSyntheticArrayMember (size_t index, bool can_create) { const uint32_t type_info = GetTypeInfo (); - if (type_info & ClangASTType::eTypeIsArray) + if (type_info & eTypeIsArray) return GetSyntheticArrayMemberFromArray(index, can_create); - if (type_info & ClangASTType::eTypeIsPointer) + if (type_info & eTypeIsPointer) return GetSyntheticArrayMemberFromPointer(index, can_create); return ValueObjectSP(); @@ -2460,6 +2485,46 @@ ValueObject::IsBaseClass (uint32_t& depth) void ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat epformat) { + // synthetic children do not actually "exist" as part of the hierarchy, and 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) + { + UpdateValueIfNeeded(); + + if (m_value.GetValueType() == Value::eValueTypeLoadAddress) + { + if (IsPointerOrReferenceType()) + { + s.Printf("((%s)0x%" PRIx64 ")", + GetTypeName().AsCString("void"), + GetValueAsUnsigned(0)); + return; + } + else + { + uint64_t load_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + if (load_addr != LLDB_INVALID_ADDRESS) + { + s.Printf("(*( (%s *)0x%" PRIx64 "))", + GetTypeName().AsCString("void"), + load_addr); + return; + } + } + } + + if (CanProvideValue()) + { + s.Printf("((%s)%s)", + GetTypeName().AsCString("void"), + GetValueAsCString()); + return; + } + + return; + } + const bool is_deref_of_parent = IsDereferenceOfParent (); if (is_deref_of_parent && epformat == eGetExpressionPathFormatDereferencePointers) @@ -2499,12 +2564,12 @@ ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExp { const uint32_t non_base_class_parent_type_info = non_base_class_parent_clang_type.GetTypeInfo(); - if (non_base_class_parent_type_info & ClangASTType::eTypeIsPointer) + if (non_base_class_parent_type_info & eTypeIsPointer) { s.PutCString("->"); } - else if ((non_base_class_parent_type_info & ClangASTType::eTypeHasChildren) && - !(non_base_class_parent_type_info & ClangASTType::eTypeIsArray)) + else if ((non_base_class_parent_type_info & eTypeHasChildren) && + !(non_base_class_parent_type_info & eTypeIsArray)) { s.PutChar('.'); } @@ -2728,15 +2793,15 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, case '-': { if (options.m_check_dot_vs_arrow_syntax && - root_clang_type_info.Test(ClangASTType::eTypeIsPointer) ) // if you are trying to use -> on a non-pointer and I must catch the error + root_clang_type_info.Test(eTypeIsPointer) ) // if you are trying to use -> on a non-pointer and I must catch the error { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot; *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } - if (root_clang_type_info.Test(ClangASTType::eTypeIsObjC) && // if yo are trying to extract an ObjC IVar when this is forbidden - root_clang_type_info.Test(ClangASTType::eTypeIsPointer) && + if (root_clang_type_info.Test(eTypeIsObjC) && // if yo are trying to extract an ObjC IVar when this is forbidden + root_clang_type_info.Test(eTypeIsPointer) && options.m_no_fragile_ivar) { *first_unparsed = expression_cstr; @@ -2756,7 +2821,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, case '.': // or fallthrough from -> { if (options.m_check_dot_vs_arrow_syntax && *expression_cstr == '.' && - root_clang_type_info.Test(ClangASTType::eTypeIsPointer)) // if you are trying to use . on a pointer and I must catch the error + root_clang_type_info.Test(eTypeIsPointer)) // if you are trying to use . on a pointer and I must catch the error { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow; @@ -2783,7 +2848,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, if (root->IsSynthetic()) { *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchSyntheticChild; *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } @@ -2857,9 +2922,9 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } case '[': { - if (!root_clang_type_info.Test(ClangASTType::eTypeIsArray) && !root_clang_type_info.Test(ClangASTType::eTypeIsPointer) && !root_clang_type_info.Test(ClangASTType::eTypeIsVector)) // if this is not a T[] nor a T* + if (!root_clang_type_info.Test(eTypeIsArray) && !root_clang_type_info.Test(eTypeIsPointer) && !root_clang_type_info.Test(eTypeIsVector)) // if this is not a T[] nor a T* { - if (!root_clang_type_info.Test(ClangASTType::eTypeIsScalar)) // if this is not even a scalar... + if (!root_clang_type_info.Test(eTypeIsScalar)) // if this is not even a scalar... { if (options.m_no_synthetic_children) // ...only chance left is synthetic { @@ -2879,7 +2944,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays { - if (!root_clang_type_info.Test(ClangASTType::eTypeIsArray)) + if (!root_clang_type_info.Test(eTypeIsArray)) { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed; @@ -2916,7 +2981,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays { - if (root_clang_type_info.Test(ClangASTType::eTypeIsArray)) + if (root_clang_type_info.Test(eTypeIsArray)) { *first_unparsed = expression_cstr+2; *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet; @@ -2932,7 +2997,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } } // from here on we do have a valid index - if (root_clang_type_info.Test(ClangASTType::eTypeIsArray)) + if (root_clang_type_info.Test(eTypeIsArray)) { ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true); if (!child_valobj_sp) @@ -2955,10 +3020,10 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, return ValueObjectSP(); } } - else if (root_clang_type_info.Test(ClangASTType::eTypeIsPointer)) + else if (root_clang_type_info.Test(eTypeIsPointer)) { if (*what_next == ValueObject::eExpressionPathAftermathDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield - pointee_clang_type_info.Test(ClangASTType::eTypeIsScalar)) + pointee_clang_type_info.Test(eTypeIsScalar)) { Error error; root = root->Dereference(error); @@ -2978,7 +3043,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, else { if (root->GetClangType().GetMinimumLanguage() == eLanguageTypeObjC - && pointee_clang_type_info.AllClear(ClangASTType::eTypeIsPointer) + && pointee_clang_type_info.AllClear(eTypeIsPointer) && root->HasSyntheticValue() && options.m_no_synthetic_children == false) { @@ -3001,7 +3066,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } } } - else if (root_clang_type_info.Test(ClangASTType::eTypeIsScalar)) + else if (root_clang_type_info.Test(eTypeIsScalar)) { root = root->GetSyntheticBitFieldChild(index, index, true); if (!root.get()) @@ -3019,7 +3084,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, return root; } } - else if (root_clang_type_info.Test(ClangASTType::eTypeIsVector)) + else if (root_clang_type_info.Test(eTypeIsVector)) { root = root->GetChildAtIndex(index, true); if (!root.get()) @@ -3104,7 +3169,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, index_lower = index_higher; index_higher = temp; } - if (root_clang_type_info.Test(ClangASTType::eTypeIsScalar)) // expansion only works for scalars + if (root_clang_type_info.Test(eTypeIsScalar)) // expansion only works for scalars { root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true); if (!root.get()) @@ -3122,9 +3187,9 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, return root; } } - else if (root_clang_type_info.Test(ClangASTType::eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield + else if (root_clang_type_info.Test(eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield *what_next == ValueObject::eExpressionPathAftermathDereference && - pointee_clang_type_info.Test(ClangASTType::eTypeIsScalar)) + pointee_clang_type_info.Test(eTypeIsScalar)) { Error error; root = root->Dereference(error); @@ -3201,9 +3266,9 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, { case '[': { - if (!root_clang_type_info.Test(ClangASTType::eTypeIsArray) && !root_clang_type_info.Test(ClangASTType::eTypeIsPointer)) // if this is not a T[] nor a T* + if (!root_clang_type_info.Test(eTypeIsArray) && !root_clang_type_info.Test(eTypeIsPointer)) // if this is not a T[] nor a T* { - if (!root_clang_type_info.Test(ClangASTType::eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong! + if (!root_clang_type_info.Test(eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong! { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid; @@ -3220,7 +3285,7 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, } if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays { - if (!root_clang_type_info.Test(ClangASTType::eTypeIsArray)) + if (!root_clang_type_info.Test(eTypeIsArray)) { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed; @@ -3264,7 +3329,7 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, } if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays { - if (root_clang_type_info.Test(ClangASTType::eTypeIsArray)) + if (root_clang_type_info.Test(eTypeIsArray)) { const size_t max_index = root->GetNumChildren() - 1; for (size_t index = 0; index < max_index; index++) @@ -3287,7 +3352,7 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, } } // from here on we do have a valid index - if (root_clang_type_info.Test(ClangASTType::eTypeIsArray)) + if (root_clang_type_info.Test(eTypeIsArray)) { root = root->GetChildAtIndex(index, true); if (!root.get()) @@ -3306,10 +3371,10 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, return 1; } } - else if (root_clang_type_info.Test(ClangASTType::eTypeIsPointer)) + else if (root_clang_type_info.Test(eTypeIsPointer)) { if (*what_next == ValueObject::eExpressionPathAftermathDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield - pointee_clang_type_info.Test(ClangASTType::eTypeIsScalar)) + pointee_clang_type_info.Test(eTypeIsScalar)) { Error error; root = root->Dereference(error); @@ -3391,7 +3456,7 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, index_lower = index_higher; index_higher = temp; } - if (root_clang_type_info.Test(ClangASTType::eTypeIsScalar)) // expansion only works for scalars + if (root_clang_type_info.Test(eTypeIsScalar)) // expansion only works for scalars { root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true); if (!root.get()) @@ -3410,9 +3475,9 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, return 1; } } - else if (root_clang_type_info.Test(ClangASTType::eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield + else if (root_clang_type_info.Test(eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield *what_next == ValueObject::eExpressionPathAftermathDereference && - pointee_clang_type_info.Test(ClangASTType::eTypeIsScalar)) + pointee_clang_type_info.Test(eTypeIsScalar)) { Error error; root = root->Dereference(error); @@ -3480,9 +3545,7 @@ ValueObject::LogValueObject (Log *log, const DumpValueObjectOptions& options) void ValueObject::Dump (Stream &s) { - - ValueObjectPrinter printer(this,&s,DumpValueObjectOptions::DefaultOptions()); - printer.PrintValueObject(); + Dump (s, DumpValueObjectOptions::DefaultOptions()); } void @@ -3529,6 +3592,55 @@ ValueObject::CreateConstantValue (const ConstString &name) return valobj_sp; } +ValueObjectSP +ValueObject::GetQualifiedRepresentationIfAvailable (lldb::DynamicValueType dynValue, + bool synthValue) +{ + ValueObjectSP result_sp(GetSP()); + + switch (dynValue) + { + case lldb::eDynamicCanRunTarget: + case lldb::eDynamicDontRunTarget: + { + if (!result_sp->IsDynamic()) + { + if (result_sp->GetDynamicValue(dynValue)) + result_sp = result_sp->GetDynamicValue(dynValue); + } + } + break; + case lldb::eNoDynamicValues: + { + if (result_sp->IsDynamic()) + { + if (result_sp->GetStaticValue()) + result_sp = result_sp->GetStaticValue(); + } + } + break; + } + + if (synthValue) + { + if (!result_sp->IsSynthetic()) + { + if (result_sp->GetSyntheticValue()) + result_sp = result_sp->GetSyntheticValue(); + } + } + else + { + if (result_sp->IsSynthetic()) + { + if (result_sp->GetNonSyntheticValue()) + result_sp = result_sp->GetNonSyntheticValue(); + } + } + + return result_sp; +} + lldb::addr_t ValueObject::GetCPPVTableAddress (AddressType &address_type) { @@ -3538,13 +3650,13 @@ ValueObject::GetCPPVTableAddress (AddressType &address_type) if (type_info) { bool ptr_or_ref = false; - if (type_info & (ClangASTType::eTypeIsPointer | ClangASTType::eTypeIsReference)) + if (type_info & (eTypeIsPointer | eTypeIsReference)) { ptr_or_ref = true; type_info = pointee_type.GetTypeInfo(); } - const uint32_t cpp_class = ClangASTType::eTypeIsClass | ClangASTType::eTypeIsCPlusPlus; + const uint32_t cpp_class = eTypeIsClass | eTypeIsCPlusPlus; if ((type_info & cpp_class) == cpp_class) { if (ptr_or_ref) @@ -3736,16 +3848,14 @@ ValueObject::CastPointerType (const char *name, TypeSP &type_sp) ValueObject::EvaluationPoint::EvaluationPoint () : m_mod_id(), m_exe_ctx_ref(), - m_needs_update (true), - m_first_update (true) + m_needs_update (true) { } ValueObject::EvaluationPoint::EvaluationPoint (ExecutionContextScope *exe_scope, bool use_selected): m_mod_id(), m_exe_ctx_ref(), - m_needs_update (true), - m_first_update (true) + m_needs_update (true) { ExecutionContext exe_ctx(exe_scope); TargetSP target_sp (exe_ctx.GetTargetSP()); @@ -3789,8 +3899,7 @@ ValueObject::EvaluationPoint::EvaluationPoint (ExecutionContextScope *exe_scope, ValueObject::EvaluationPoint::EvaluationPoint (const ValueObject::EvaluationPoint &rhs) : m_mod_id(), m_exe_ctx_ref(rhs.m_exe_ctx_ref), - m_needs_update (true), - m_first_update (true) + m_needs_update (true) { } @@ -3884,7 +3993,6 @@ ValueObject::EvaluationPoint::SetUpdated () ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP()); if (process_sp) m_mod_id = process_sp->GetModID(); - m_first_update = false; m_needs_update = false; } @@ -3900,9 +4008,7 @@ ValueObject::ClearUserVisibleData(uint32_t clear_mask) m_location_str.clear(); if ((clear_mask & eClearUserVisibleDataItemsSummary) == eClearUserVisibleDataItemsSummary) - { m_summary_str.clear(); - } if ((clear_mask & eClearUserVisibleDataItemsDescription) == eClearUserVisibleDataItemsDescription) m_object_desc_str.clear(); @@ -3912,6 +4018,9 @@ ValueObject::ClearUserVisibleData(uint32_t clear_mask) if (m_synthetic_value) m_synthetic_value = NULL; } + + if ((clear_mask & eClearUserVisibleDataItemsValidator) == eClearUserVisibleDataItemsValidator) + m_validation_result.reset(); } SymbolContextScope * @@ -3929,6 +4038,16 @@ lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression (const char* name, const char* expression, const ExecutionContext& exe_ctx) +{ + return CreateValueObjectFromExpression(name, expression, exe_ctx, EvaluateExpressionOptions()); +} + + +lldb::ValueObjectSP +ValueObject::CreateValueObjectFromExpression (const char* name, + const char* expression, + const ExecutionContext& exe_ctx, + const EvaluateExpressionOptions& options) { lldb::ValueObjectSP retval_sp; lldb::TargetSP target_sp(exe_ctx.GetTargetSP()); @@ -3938,7 +4057,8 @@ ValueObject::CreateValueObjectFromExpression (const char* name, return retval_sp; target_sp->EvaluateExpression (expression, exe_ctx.GetFrameSP().get(), - retval_sp); + retval_sp, + options); if (retval_sp && name && *name) retval_sp->SetName(ConstString(name)); return retval_sp; @@ -3960,7 +4080,7 @@ ValueObject::CreateValueObjectFromAddress (const char* name, pointer_type, ConstString(name), buffer, - lldb::endian::InlHostByteOrder(), + exe_ctx.GetByteOrder(), exe_ctx.GetAddressByteSize())); if (ptr_result_valobj_sp) { @@ -4057,3 +4177,77 @@ ValueObject::GetFormat () const } return m_format; } + +lldb::LanguageType +ValueObject::GetPreferredDisplayLanguage () +{ + lldb::LanguageType type = lldb::eLanguageTypeUnknown; + if (GetRoot()) + { + if (GetRoot() == this) + { + if (StackFrameSP frame_sp = GetFrameSP()) + { + const SymbolContext& sc(frame_sp->GetSymbolContext(eSymbolContextCompUnit)); + if (CompileUnit* cu = sc.comp_unit) + type = cu->GetLanguage(); + } + } + else + { + type = GetRoot()->GetPreferredDisplayLanguage(); + } + } + return type; +} + +bool +ValueObject::CanProvideValue () +{ + // we need to support invalid types as providers of values because some bare-board + // debugging scenarios have no notion of types, but still manage to have raw numeric + // values for things like registers. sigh. + const ClangASTType &type(GetClangType()); + return (false == type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue)); +} + +bool +ValueObject::IsChecksumEmpty () +{ + return m_value_checksum.empty(); +} + +ValueObjectSP +ValueObject::Persist () +{ + if (!UpdateValueIfNeeded()) + return nullptr; + + TargetSP target_sp(GetTargetSP()); + if (!target_sp) + return nullptr; + + ConstString name(target_sp->GetPersistentVariables().GetNextPersistentVariableName()); + + ClangExpressionVariableSP clang_var_sp(new ClangExpressionVariable(target_sp.get(), GetValue(), name)); + if (clang_var_sp) + { + clang_var_sp->m_live_sp = clang_var_sp->m_frozen_sp; + clang_var_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference; + target_sp->GetPersistentVariables().AddVariable(clang_var_sp); + } + + return clang_var_sp->GetValueObject(); +} + +bool +ValueObject::IsSyntheticChildrenGenerated () +{ + return m_is_synthetic_children_generated; +} + +void +ValueObject::SetSyntheticChildrenGenerated (bool b) +{ + m_is_synthetic_children_generated = b; +} diff --git a/source/Core/ValueObjectCast.cpp b/source/Core/ValueObjectCast.cpp index 4f4f8cc681d0..b20371b128df 100644 --- a/source/Core/ValueObjectCast.cpp +++ b/source/Core/ValueObjectCast.cpp @@ -102,7 +102,7 @@ ValueObjectCast::UpdateValue () //m_value.SetContext (Value::eContextTypeClangType, clang_type); m_value.SetClangType (clang_type); SetAddressTypeOfChildren(m_parent->GetAddressTypeOfChildren()); - if (clang_type.IsAggregateType ()) + if (!CanProvideValue()) { // this value object represents an aggregate type whose // children have values, but this object does not. So we diff --git a/source/Core/ValueObjectChild.cpp b/source/Core/ValueObjectChild.cpp index 33b91f9e30d1..2b3c8344af8f 100644 --- a/source/Core/ValueObjectChild.cpp +++ b/source/Core/ValueObjectChild.cpp @@ -208,7 +208,7 @@ ValueObjectChild::UpdateValue () { const bool thread_and_frame_only_if_stopped = true; ExecutionContext exe_ctx (GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped)); - if (GetClangType().GetTypeInfo() & ClangASTType::eTypeHasValue) + if (GetClangType().GetTypeInfo() & lldb::eTypeHasValue) m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); else m_error.Clear(); // No value so nothing to read... diff --git a/source/Core/ValueObjectConstResult.cpp b/source/Core/ValueObjectConstResult.cpp index 387e171e3526..fc870d726221 100644 --- a/source/Core/ValueObjectConstResult.cpp +++ b/source/Core/ValueObjectConstResult.cpp @@ -122,9 +122,10 @@ ValueObjectConstResult::Create (ExecutionContextScope *exe_scope, ValueObjectSP ValueObjectConstResult::Create (ExecutionContextScope *exe_scope, Value &value, - const ConstString &name) + const ConstString &name, + Module *module) { - return (new ValueObjectConstResult (exe_scope, value, name))->GetSP(); + return (new ValueObjectConstResult (exe_scope, value, name, module))->GetSP(); } ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope, @@ -222,14 +223,18 @@ ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope, const Value &value, - const ConstString &name) : + const ConstString &name, + Module *module) : ValueObject (exe_scope), m_type_name (), m_byte_size (0), m_impl(this) { m_value = value; - m_value.GetData(m_data); + m_name = name; + ExecutionContext exe_ctx; + exe_scope->CalculateExecutionContext(exe_ctx); + m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, module); } ValueObjectConstResult::~ValueObjectConstResult() @@ -358,3 +363,8 @@ ValueObjectConstResult::GetDynamicValue (lldb::DynamicValueType use_dynamic) return ValueObjectSP(); } +lldb::LanguageType +ValueObjectConstResult::GetPreferredDisplayLanguage () +{ + return lldb::eLanguageTypeUnknown; +} diff --git a/source/Core/ValueObjectConstResultImpl.cpp b/source/Core/ValueObjectConstResultImpl.cpp index d3e275883509..733d767b7ee1 100644 --- a/source/Core/ValueObjectConstResultImpl.cpp +++ b/source/Core/ValueObjectConstResultImpl.cpp @@ -30,13 +30,6 @@ using namespace lldb; using namespace lldb_private; -// this macro enables a simpler implementation for some method calls in this object that relies only upon -// ValueObject knowing how to set the address type of its children correctly. the alternative implementation -// relies on being able to create a target copy of the frozen object, which makes it less bug-prone but less -// efficient as well. once we are confident the faster implementation is bug-free, this macro (and the slower -// implementations) can go -#define TRIVIAL_IMPL 1 - ValueObjectConstResultImpl::ValueObjectConstResultImpl (ValueObject* valobj, lldb::addr_t live_address) : m_impl_backend(valobj), @@ -47,39 +40,13 @@ ValueObjectConstResultImpl::ValueObjectConstResultImpl (ValueObject* valobj, { } -lldb::ValueObjectSP -ValueObjectConstResultImpl::DerefOnTarget() -{ - if (m_load_addr_backend.get() == NULL) - { - lldb::addr_t tgt_address = m_impl_backend->GetPointerValue(); - ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef()); - m_load_addr_backend = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), - m_impl_backend->GetClangType(), - m_impl_backend->GetName(), - tgt_address, - eAddressTypeLoad, - exe_ctx.GetAddressByteSize()); - } - return m_load_addr_backend; -} - lldb::ValueObjectSP ValueObjectConstResultImpl::Dereference (Error &error) { if (m_impl_backend == NULL) return lldb::ValueObjectSP(); -#if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1 return m_impl_backend->ValueObject::Dereference(error); -#else - m_impl_backend->UpdateValueIfNeeded(false); - - if (NeedsDerefOnTarget()) - return DerefOnTarget()->Dereference(error); - else - return m_impl_backend->ValueObject::Dereference(error); -#endif } ValueObject * @@ -139,7 +106,8 @@ ValueObjectConstResultImpl::CreateChildAtIndex (size_t idx, bool synthetic_array child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent); - valobj->m_impl.SetLiveAddress(m_live_address+child_byte_offset); + if (m_live_address != LLDB_INVALID_ADDRESS) + valobj->m_impl.SetLiveAddress(m_live_address+child_byte_offset); } return valobj; @@ -151,16 +119,7 @@ ValueObjectConstResultImpl::GetSyntheticChildAtOffset (uint32_t offset, const Cl if (m_impl_backend == NULL) return lldb::ValueObjectSP(); -#if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1 return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(offset, type, can_create); -#else - m_impl_backend->UpdateValueIfNeeded(false); - - if (NeedsDerefOnTarget()) - return DerefOnTarget()->GetSyntheticChildAtOffset(offset, type, can_create); - else - return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(offset, type, can_create); -#endif } lldb::ValueObjectSP @@ -193,7 +152,7 @@ ValueObjectConstResultImpl::AddressOf (Error &error) return m_address_of_backend; } else - return lldb::ValueObjectSP(); + return m_impl_backend->ValueObject::AddressOf(error); } lldb::addr_t @@ -223,14 +182,5 @@ ValueObjectConstResultImpl::GetPointeeData (DataExtractor& data, { if (m_impl_backend == NULL) return 0; -#if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1 return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count); -#else - m_impl_backend->UpdateValueIfNeeded(false); - - if (NeedsDerefOnTarget() && m_impl_backend->IsPointerType()) - return DerefOnTarget()->GetPointeeData(data, item_idx, item_count); - else - return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count); -#endif } diff --git a/source/Core/ValueObjectDynamicValue.cpp b/source/Core/ValueObjectDynamicValue.cpp index a6fad7a9b1fd..1b8ec8083f8f 100644 --- a/source/Core/ValueObjectDynamicValue.cpp +++ b/source/Core/ValueObjectDynamicValue.cpp @@ -241,16 +241,7 @@ ValueObjectDynamicValue::UpdateValue () { if (class_type_or_name.HasType()) { - // TypeSP are always generated from debug info - if (!class_type_or_name.HasTypeSP() && class_type_or_name.GetClangASTType().IsRuntimeGeneratedType()) - { - m_type_impl = TypeImpl(m_parent->GetClangType(),FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType()); - class_type_or_name.SetClangASTType(ClangASTType()); - } - else - { - m_type_impl = TypeImpl(FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType()); - } + m_type_impl = TypeImpl(m_parent->GetClangType(),FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType()); } else { @@ -329,7 +320,7 @@ ValueObjectDynamicValue::UpdateValue () m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); if (m_error.Success()) { - if (GetClangType().IsAggregateType ()) + if (!CanProvideValue()) { // this value object represents an aggregate type whose // children have values, but this object does not. So we diff --git a/source/Core/ValueObjectMemory.cpp b/source/Core/ValueObjectMemory.cpp index d2cbbfdda240..5fbe87b66522 100644 --- a/source/Core/ValueObjectMemory.cpp +++ b/source/Core/ValueObjectMemory.cpp @@ -233,7 +233,7 @@ ValueObjectMemory::UpdateValue () } } - if (GetClangType().IsAggregateType()) + if (!CanProvideValue()) { // this value object represents an aggregate type whose // children have values, but this object does not. So we diff --git a/source/Core/ValueObjectSyntheticFilter.cpp b/source/Core/ValueObjectSyntheticFilter.cpp index 18d36164989a..dafe73a5e57e 100644 --- a/source/Core/ValueObjectSyntheticFilter.cpp +++ b/source/Core/ValueObjectSyntheticFilter.cpp @@ -66,16 +66,17 @@ ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::Synthetic m_name_toindex(), m_synthetic_children_count(UINT32_MAX), m_parent_type_name(parent.GetTypeName()), - m_might_have_children(eLazyBoolCalculate) + m_might_have_children(eLazyBoolCalculate), + m_provides_value(eLazyBoolCalculate) { -#ifdef LLDB_CONFIGURATION_DEBUG +#ifdef FOOBAR std::string new_name(parent.GetName().AsCString()); new_name += "$$__synth__"; SetName (ConstString(new_name.c_str())); #else SetName(parent.GetName()); #endif - CopyParentData(); + CopyValueData(m_parent); CreateSynthFilter(); } @@ -181,8 +182,8 @@ ValueObjectSynthetic::UpdateValue () if (m_synth_filter_ap->Update() == false) { // filter said that cached values are stale - m_children_byindex.clear(); - m_name_toindex.clear(); + m_children_byindex.Clear(); + m_name_toindex.Clear(); // usually, an object's value can change but this does not alter its children count // for a synthetic VO that might indeed happen, so we need to tell the upper echelons // that they need to come back to us asking for children @@ -191,7 +192,20 @@ ValueObjectSynthetic::UpdateValue () m_might_have_children = eLazyBoolCalculate; } - CopyParentData(); + m_provides_value = eLazyBoolCalculate; + + lldb::ValueObjectSP synth_val(m_synth_filter_ap->GetSyntheticValue()); + + if (synth_val && synth_val->CanProvideValue()) + { + m_provides_value = eLazyBoolYes; + CopyValueData(synth_val.get()); + } + else + { + m_provides_value = eLazyBoolNo; + CopyValueData(m_parent); + } SetValueIsValid(true); return true; @@ -202,23 +216,22 @@ ValueObjectSynthetic::GetChildAtIndex (size_t idx, bool can_create) { UpdateValueIfNeeded(); - ByIndexIterator iter = m_children_byindex.find(idx); - - if (iter == m_children_byindex.end()) + ValueObject *valobj; + if (m_children_byindex.GetValueForKey(idx, valobj) == false) { if (can_create && m_synth_filter_ap.get() != NULL) { lldb::ValueObjectSP synth_guy = m_synth_filter_ap->GetChildAtIndex (idx); if (!synth_guy) return synth_guy; - m_children_byindex[idx]= synth_guy.get(); + m_children_byindex.SetValueForKey(idx, synth_guy.get()); return synth_guy; } else return lldb::ValueObjectSP(); } else - return iter->second->GetSP(); + return valobj->GetSP(); } lldb::ValueObjectSP @@ -239,20 +252,21 @@ ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name) { UpdateValueIfNeeded(); - NameToIndexIterator iter = m_name_toindex.find(name.GetCString()); + uint32_t found_index = UINT32_MAX; + bool did_find = m_name_toindex.GetValueForKey(name.GetCString(), found_index); - if (iter == m_name_toindex.end() && m_synth_filter_ap.get() != NULL) + if (!did_find && m_synth_filter_ap.get() != NULL) { uint32_t index = m_synth_filter_ap->GetIndexOfChildWithName (name); if (index == UINT32_MAX) return index; - m_name_toindex[name.GetCString()] = index; + m_name_toindex.SetValueForKey(name.GetCString(), index); return index; } - else if (iter == m_name_toindex.end() && m_synth_filter_ap.get() == NULL) + else if (!did_find && m_synth_filter_ap.get() == NULL) return UINT32_MAX; else /*if (iter != m_name_toindex.end())*/ - return iter->second; + return found_index; } bool @@ -268,9 +282,19 @@ ValueObjectSynthetic::GetNonSyntheticValue () } void -ValueObjectSynthetic::CopyParentData () +ValueObjectSynthetic::CopyValueData (ValueObject *source) { - m_value = m_parent->GetValue(); + m_value = (source->UpdateValueIfNeeded(), source->GetValue()); ExecutionContext exe_ctx (GetExecutionContextRef()); m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); } + +bool +ValueObjectSynthetic::CanProvideValue () +{ + if (!UpdateValueIfNeeded()) + return false; + if (m_provides_value == eLazyBoolYes) + return true; + return m_parent->CanProvideValue(); +} diff --git a/source/Core/ValueObjectVariable.cpp b/source/Core/ValueObjectVariable.cpp index 225dc02c8add..ab74a50e7cd5 100644 --- a/source/Core/ValueObjectVariable.cpp +++ b/source/Core/ValueObjectVariable.cpp @@ -171,14 +171,44 @@ ValueObjectVariable::UpdateValue () m_value.SetClangType(clang_type); Value::ValueType value_type = m_value.GetValueType(); - + + Process *process = exe_ctx.GetProcessPtr(); + const bool process_is_alive = process && process->IsAlive(); + const uint32_t type_info = clang_type.GetTypeInfo(); + const bool is_pointer_or_ref = (type_info & (lldb::eTypeIsPointer | lldb::eTypeIsReference)) != 0; + switch (value_type) { case Value::eValueTypeFileAddress: - SetAddressTypeOfChildren(eAddressTypeFile); + // If this type is a pointer, then its children will be considered load addresses + // if the pointer or reference is dereferenced, but only if the process is alive. + // + // There could be global variables like in the following code: + // struct LinkedListNode { Foo* foo; LinkedListNode* next; }; + // Foo g_foo1; + // Foo g_foo2; + // LinkedListNode g_second_node = { &g_foo2, NULL }; + // LinkedListNode g_first_node = { &g_foo1, &g_second_node }; + // + // When we aren't running, we should be able to look at these variables using + // the "target variable" command. Children of the "g_first_node" always will + // be of the same address type as the parent. But children of the "next" member of + // LinkedListNode will become load addresses if we have a live process, or remain + // what a file address if it what a file address. + if (process_is_alive && is_pointer_or_ref) + SetAddressTypeOfChildren(eAddressTypeLoad); + else + SetAddressTypeOfChildren(eAddressTypeFile); break; case Value::eValueTypeHostAddress: - SetAddressTypeOfChildren(eAddressTypeHost); + // Same as above for load addresses, except children of pointer or refs are always + // load addresses. Host addresses are used to store freeze dried variables. If this + // type is a struct, the entire struct contents will be copied into the heap of the + // LLDB process, but we do not currrently follow any pointers. + if (is_pointer_or_ref) + SetAddressTypeOfChildren(eAddressTypeLoad); + else + SetAddressTypeOfChildren(eAddressTypeHost); break; case Value::eValueTypeLoadAddress: case Value::eValueTypeScalar: @@ -209,8 +239,7 @@ ValueObjectVariable::UpdateValue () // 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. - Process *process = exe_ctx.GetProcessPtr(); - if (value_type == Value::eValueTypeFileAddress && process && process->IsAlive()) + if (value_type == Value::eValueTypeFileAddress && process_is_alive) { lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); if (file_addr != LLDB_INVALID_ADDRESS) @@ -234,7 +263,7 @@ ValueObjectVariable::UpdateValue () } } - if (GetClangType().IsAggregateType()) + if (!CanProvideValue()) { // this value object represents an aggregate type whose // children have values, but this object does not. So we @@ -248,6 +277,8 @@ ValueObjectVariable::UpdateValue () Value value(m_value); value.SetContext(Value::eContextTypeVariable, variable); m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + + SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); } break; } diff --git a/source/DataFormatters/CF.cpp b/source/DataFormatters/CF.cpp index e131b68096fd..483419e5ac3f 100644 --- a/source/DataFormatters/CF.cpp +++ b/source/DataFormatters/CF.cpp @@ -26,7 +26,7 @@ using namespace lldb_private; using namespace lldb_private::formatters; bool -lldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { time_t epoch = GetOSXEpoch(); epoch = epoch + (time_t)valobj.GetValueAsUnsigned(0); @@ -41,7 +41,7 @@ lldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, St } bool -lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -105,7 +105,7 @@ lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& str } bool -lldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -235,7 +235,7 @@ lldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Strea } bool -lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) diff --git a/source/DataFormatters/CXXFormatterFunctions.cpp b/source/DataFormatters/CXXFormatterFunctions.cpp index ae5b35fd2b1c..04cdadf5a98f 100644 --- a/source/DataFormatters/CXXFormatterFunctions.cpp +++ b/source/DataFormatters/CXXFormatterFunctions.cpp @@ -10,6 +10,8 @@ #include "lldb/lldb-python.h" #include "lldb/DataFormatters/CXXFormatterFunctions.h" +#include "lldb/DataFormatters/StringPrinter.h" +#include "lldb/DataFormatters/TypeSummary.h" #include "llvm/Support/ConvertUTF.h" @@ -20,10 +22,16 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Host/Endian.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/ProcessStructReader.h" + #include +#if __ANDROID_NDK__ +#include +#endif using namespace lldb; using namespace lldb_private; @@ -187,283 +195,53 @@ lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj, return valobj_sp; } -// use this call if you already have an LLDB-side buffer for the data -template -static bool -DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**, - const SourceDataType*, - UTF8**, - UTF8*, - ConversionFlags), - DataExtractor& data, - Stream& stream, - char prefix_token = '@', - char quote = '"', - uint32_t sourceSize = 0) +bool +lldb_private::formatters::FunctionPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { - if (prefix_token != 0) - stream.Printf("%c",prefix_token); - if (quote != 0) - stream.Printf("%c",quote); - if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd()) + std::string destination; + StreamString sstr; + AddressType func_ptr_address_type = eAddressTypeInvalid; + addr_t func_ptr_address = valobj.GetPointerValue (&func_ptr_address_type); + if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) { - const int bufferSPSize = data.GetByteSize(); - if (sourceSize == 0) - { - const int origin_encoding = 8*sizeof(SourceDataType); - sourceSize = bufferSPSize/(origin_encoding / 4); - } - - SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart(); - SourceDataType *data_end_ptr = data_ptr + sourceSize; - - while (data_ptr < data_end_ptr) + switch (func_ptr_address_type) { - if (!*data_ptr) - { - data_end_ptr = data_ptr; + case eAddressTypeInvalid: + case eAddressTypeFile: + case eAddressTypeHost: break; + + case eAddressTypeLoad: + { + ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); + + Address so_addr; + Target *target = exe_ctx.GetTargetPtr(); + if (target && target->GetSectionLoadList().IsEmpty() == false) + { + if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr)) + { + so_addr.Dump (&sstr, + exe_ctx.GetBestExecutionContextScope(), + Address::DumpStyleResolvedDescription, + Address::DumpStyleSectionNameOffset); + } + } } - data_ptr++; - } - - data_ptr = (SourceDataType*)data.GetDataStart(); - - lldb::DataBufferSP utf8_data_buffer_sp; - UTF8* utf8_data_ptr = nullptr; - UTF8* utf8_data_end_ptr = nullptr; - - if (ConvertFunction) - { - utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0)); - utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); - utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize(); - ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion ); - utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr - } - else - { - // just copy the pointers - the cast is necessary to make the compiler happy - // but this should only happen if we are reading UTF8 data - utf8_data_ptr = (UTF8*)data_ptr; - utf8_data_end_ptr = (UTF8*)data_end_ptr; - } - - // since we tend to accept partial data (and even partially malformed data) - // we might end up with no NULL terminator before the end_ptr - // hence we need to take a slower route and ensure we stay within boundaries - for (;utf8_data_ptr != utf8_data_end_ptr; utf8_data_ptr++) - { - if (!*utf8_data_ptr) break; - stream.Printf("%c",*utf8_data_ptr); } } - if (quote != 0) - stream.Printf("%c",quote); - return true; -} - -template -class ReadUTFBufferAndDumpToStreamOptions -{ -public: - typedef ConversionResult (*ConvertFunctionType) (const SourceDataType**, - const SourceDataType*, - UTF8**, - UTF8*, - ConversionFlags); - - ReadUTFBufferAndDumpToStreamOptions () : - m_conversion_function(NULL), - m_location(0), - m_process_sp(), - m_stream(NULL), - m_prefix_token('@'), - m_quote('"'), - m_source_size(0), - m_needs_zero_termination(true) - { - } - - ReadUTFBufferAndDumpToStreamOptions& - SetConversionFunction (ConvertFunctionType f) - { - m_conversion_function = f; - return *this; - } - - ConvertFunctionType - GetConversionFunction () const - { - return m_conversion_function; - } - - ReadUTFBufferAndDumpToStreamOptions& - SetLocation (uint64_t l) - { - m_location = l; - return *this; - } - - uint64_t - GetLocation () const - { - return m_location; - } - - ReadUTFBufferAndDumpToStreamOptions& - SetProcessSP (ProcessSP p) - { - m_process_sp = p; - return *this; - } - - ProcessSP - GetProcessSP () const - { - return m_process_sp; - } - - ReadUTFBufferAndDumpToStreamOptions& - SetStream (Stream* s) - { - m_stream = s; - return *this; - } - - Stream* - GetStream () const - { - return m_stream; - } - - ReadUTFBufferAndDumpToStreamOptions& - SetPrefixToken (char p) - { - m_prefix_token = p; - return *this; - } - - char - GetPrefixToken () const - { - return m_prefix_token; - } - - ReadUTFBufferAndDumpToStreamOptions& - SetQuote (char q) - { - m_quote = q; - return *this; - } - - char - GetQuote () const - { - return m_quote; - } - - ReadUTFBufferAndDumpToStreamOptions& - SetSourceSize (uint32_t s) - { - m_source_size = s; - return *this; - } - - uint32_t - GetSourceSize () const - { - return m_source_size; - } - - ReadUTFBufferAndDumpToStreamOptions& - SetNeedsZeroTermination (bool z) + if (sstr.GetSize() > 0) { - m_needs_zero_termination = z; - return *this; - } - - bool - GetNeedsZeroTermination () const - { - return m_needs_zero_termination; - } - -private: - ConvertFunctionType m_conversion_function; - uint64_t m_location; - ProcessSP m_process_sp; - Stream* m_stream; - char m_prefix_token; - char m_quote; - uint32_t m_source_size; - bool m_needs_zero_termination; -}; - -template -static bool -ReadUTFBufferAndDumpToStream (const ReadUTFBufferAndDumpToStreamOptions& options) -{ - if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS) - return false; - - ProcessSP process_sp(options.GetProcessSP()); - - if (!process_sp) - return false; - - const int type_width = sizeof(SourceDataType); - const int origin_encoding = 8 * type_width ; - if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32) - return false; - // if not UTF8, I need a conversion function to return proper UTF8 - if (origin_encoding != 8 && !options.GetConversionFunction()) - return false; - - if (!options.GetStream()) - return false; - - uint32_t sourceSize = options.GetSourceSize(); - bool needs_zero_terminator = options.GetNeedsZeroTermination(); - - if (!sourceSize) - { - sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); - needs_zero_terminator = true; + stream.Printf("(%s)", sstr.GetData()); + return true; } else - sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary()); - - const int bufferSPSize = sourceSize * type_width; - - lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0)); - - if (!buffer_sp->GetBytes()) return false; - - Error error; - char *buffer = reinterpret_cast(buffer_sp->GetBytes()); - - size_t data_read = 0; - if (needs_zero_terminator) - data_read = process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width); - else - data_read = process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error); - - if (error.Fail() || data_read == 0) - { - options.GetStream()->Printf("unable to read data"); - return true; - } - - DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); - - return DumpUTFBufferToStream(options.GetConversionFunction(), data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize); } bool -lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -474,14 +252,13 @@ lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stre if (!valobj_addr) return false; - ReadUTFBufferAndDumpToStreamOptions options; + ReadStringAndDumpToStreamOptions options(valobj); options.SetLocation(valobj_addr); - options.SetConversionFunction(ConvertUTF16toUTF8); options.SetProcessSP(process_sp); options.SetStream(&stream); options.SetPrefixToken('u'); - if (!ReadUTFBufferAndDumpToStream(options)) + if (!ReadStringAndDumpToStream(options)) { stream.Printf("Summary Unavailable"); return true; @@ -491,7 +268,7 @@ lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stre } bool -lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -502,14 +279,13 @@ lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stre if (!valobj_addr) return false; - ReadUTFBufferAndDumpToStreamOptions options; + ReadStringAndDumpToStreamOptions options(valobj); options.SetLocation(valobj_addr); - options.SetConversionFunction(ConvertUTF32toUTF8); options.SetProcessSP(process_sp); options.SetStream(&stream); options.SetPrefixToken('U'); - if (!ReadUTFBufferAndDumpToStream(options)) + if (!ReadStringAndDumpToStream(options)) { stream.Printf("Summary Unavailable"); return true; @@ -519,7 +295,7 @@ lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stre } bool -lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -543,45 +319,20 @@ lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Strea ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar); const uint32_t wchar_size = wchar_clang_type.GetBitSize(); + ReadStringAndDumpToStreamOptions options(valobj); + options.SetLocation(data_addr); + options.SetProcessSP(process_sp); + options.SetStream(&stream); + options.SetPrefixToken('L'); + switch (wchar_size) { case 8: - { - // utf 8 - - ReadUTFBufferAndDumpToStreamOptions options; - options.SetLocation(data_addr); - options.SetConversionFunction(nullptr); - options.SetProcessSP(process_sp); - options.SetStream(&stream); - options.SetPrefixToken('L'); - - return ReadUTFBufferAndDumpToStream(options); - } + return ReadStringAndDumpToStream(options); case 16: - { - // utf 16 - ReadUTFBufferAndDumpToStreamOptions options; - options.SetLocation(data_addr); - options.SetConversionFunction(ConvertUTF16toUTF8); - options.SetProcessSP(process_sp); - options.SetStream(&stream); - options.SetPrefixToken('L'); - - return ReadUTFBufferAndDumpToStream(options); - } + return ReadStringAndDumpToStream(options); case 32: - { - // utf 32 - ReadUTFBufferAndDumpToStreamOptions options; - options.SetLocation(data_addr); - options.SetConversionFunction(ConvertUTF32toUTF8); - options.SetProcessSP(process_sp); - options.SetStream(&stream); - options.SetPrefixToken('L'); - - return ReadUTFBufferAndDumpToStream(options); - } + return ReadStringAndDumpToStream(options); default: stream.Printf("size for wchar_t is not valid"); return true; @@ -590,7 +341,7 @@ lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Strea } bool -lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) { DataExtractor data; Error error; @@ -604,11 +355,18 @@ lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& st if (!value.empty()) stream.Printf("%s ", value.c_str()); - return DumpUTFBufferToStream(ConvertUTF16toUTF8,data,stream, 'u','\'',1); + ReadBufferAndDumpToStreamOptions options(valobj); + options.SetData(data); + options.SetStream(&stream); + options.SetPrefixToken('u'); + options.SetQuote('\''); + options.SetSourceSize(1); + + return ReadBufferAndDumpToStream(options); } bool -lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) { DataExtractor data; Error error; @@ -622,11 +380,18 @@ lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& st if (!value.empty()) stream.Printf("%s ", value.c_str()); - return DumpUTFBufferToStream(ConvertUTF32toUTF8,data,stream, 'U','\'',1); + ReadBufferAndDumpToStreamOptions options(valobj); + options.SetData(data); + options.SetStream(&stream); + options.SetPrefixToken('U'); + options.SetQuote('\''); + options.SetSourceSize(1); + + return ReadBufferAndDumpToStream(options); } bool -lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) { DataExtractor data; Error error; @@ -635,55 +400,14 @@ lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& str if (error.Fail()) return false; - clang::ASTContext* ast = valobj.GetClangType().GetASTContext(); - - if (!ast) - return false; - - ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar); - const uint32_t wchar_size = wchar_clang_type.GetBitSize(); - std::string value; + ReadBufferAndDumpToStreamOptions options(valobj); + options.SetData(data); + options.SetStream(&stream); + options.SetPrefixToken('L'); + options.SetQuote('\''); + options.SetSourceSize(1); - switch (wchar_size) - { - case 8: - // utf 8 - valobj.GetValueAsCString(lldb::eFormatChar, value); - if (!value.empty()) - stream.Printf("%s ", value.c_str()); - return DumpUTFBufferToStream(nullptr, - data, - stream, - 'L', - '\'', - 1); - case 16: - // utf 16 - valobj.GetValueAsCString(lldb::eFormatUnicode16, value); - if (!value.empty()) - stream.Printf("%s ", value.c_str()); - return DumpUTFBufferToStream(ConvertUTF16toUTF8, - data, - stream, - 'L', - '\'', - 1); - case 32: - // utf 32 - valobj.GetValueAsCString(lldb::eFormatUnicode32, value); - if (!value.empty()) - stream.Printf("%s ", value.c_str()); - return DumpUTFBufferToStream(ConvertUTF32toUTF8, - data, - stream, - 'L', - '\'', - 1); - default: - stream.Printf("size for wchar_t is not valid"); - return true; - } - return true; + return ReadBufferAndDumpToStream(options); } // the field layout in a libc++ string (cap, side, data or data, size, cap) @@ -769,7 +493,7 @@ ExtractLibcxxStringInfo (ValueObject& valobj, } bool -lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { uint64_t size = 0; ValueObjectSP location_sp((ValueObject*)nullptr); @@ -782,34 +506,45 @@ lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Str } if (!location_sp) return false; - return WCharStringSummaryProvider(*location_sp.get(), stream); + return WCharStringSummaryProvider(*location_sp.get(), stream, options); } bool -lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options) { uint64_t size = 0; ValueObjectSP location_sp((ValueObject*)nullptr); + if (!ExtractLibcxxStringInfo(valobj, location_sp, size)) return false; + if (size == 0) { stream.Printf("\"\""); return true; } + if (!location_sp) return false; - Error error; - if (location_sp->ReadPointedString(stream, - error, - 0, // max length is decided by the settings - false) == 0) // do not honor array (terminates on first 0 byte even for a char[]) - stream.Printf("\"\""); // if nothing was read, print an empty string - return error.Success(); + + DataExtractor extractor; + if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) + size = std::min(size, valobj.GetTargetSP()->GetMaximumSizeOfStringSummary()); + location_sp->GetPointeeData(extractor, 0, size); + + ReadBufferAndDumpToStreamOptions options(valobj); + options.SetData(extractor); // none of this matters for a string - pass some defaults + options.SetStream(&stream); + options.SetPrefixToken(0); + options.SetQuote('"'); + options.SetSourceSize(size); + lldb_private::formatters::ReadBufferAndDumpToStream(options); + + return true; } bool -lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -886,7 +621,7 @@ lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildre template bool -lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -1037,8 +772,28 @@ lldb_private::formatters::NSTaggedString_SummaryProvider (ObjCLanguageRuntime::C return true; } +static ClangASTType +GetNSPathStore2Type (Target &target) +{ + static ConstString g_type_name("__lldb_autogen_nspathstore2"); + + ClangASTContext *ast_ctx = target.GetScratchClangASTContext(); + + if (!ast_ctx) + return ClangASTType(); + + ClangASTType voidstar = ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType(); + ClangASTType uint32 = ast_ctx->GetIntTypeFromBitSize(32, false); + + return ast_ctx->GetOrCreateStructForIdentifier(g_type_name, { + {"isa",voidstar}, + {"lengthAndRef",uint32}, + {"buffer",voidstar} + }); +} + bool -lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -1131,8 +886,7 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& return false; if (has_explicit_length && is_unicode) { - ReadUTFBufferAndDumpToStreamOptions options; - options.SetConversionFunction(ConvertUTF16toUTF8); + ReadStringAndDumpToStreamOptions options(valobj); options.SetLocation(location); options.SetProcessSP(process_sp); options.SetStream(&stream); @@ -1140,10 +894,21 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& options.SetQuote('"'); options.SetSourceSize(explicit_length); options.SetNeedsZeroTermination(false); - return ReadUTFBufferAndDumpToStream (options); + options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); + return ReadStringAndDumpToStream(options); } else - return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length); + { + ReadStringAndDumpToStreamOptions options(valobj); + options.SetLocation(location+1); + options.SetProcessSP(process_sp); + options.SetStream(&stream); + options.SetPrefixToken('@'); + options.SetSourceSize(explicit_length); + options.SetNeedsZeroTermination(false); + options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); + return ReadStringAndDumpToStream(options); + } } else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable) { @@ -1169,8 +934,7 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& if (error.Fail()) return false; } - ReadUTFBufferAndDumpToStreamOptions options; - options.SetConversionFunction(ConvertUTF16toUTF8); + ReadStringAndDumpToStreamOptions options(valobj); options.SetLocation(location); options.SetProcessSP(process_sp); options.SetStream(&stream); @@ -1178,13 +942,16 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& options.SetQuote('"'); options.SetSourceSize(explicit_length); options.SetNeedsZeroTermination(has_explicit_length == false); - return ReadUTFBufferAndDumpToStream (options); + options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); + return ReadStringAndDumpToStream (options); } else if (is_special) { - uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8); - ReadUTFBufferAndDumpToStreamOptions options; - options.SetConversionFunction(ConvertUTF16toUTF8); + ProcessStructReader reader(valobj.GetProcessSP().get(), valobj.GetValueAsUnsigned(0), GetNSPathStore2Type(*valobj.GetTargetSP())); + explicit_length = reader.GetField(ConstString("lengthAndRef")) >> 20; + lldb::addr_t location = valobj.GetValueAsUnsigned(0) + ptr_size + 4; + + ReadStringAndDumpToStreamOptions options(valobj); options.SetLocation(location); options.SetProcessSP(process_sp); options.SetStream(&stream); @@ -1192,14 +959,22 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& options.SetQuote('"'); options.SetSourceSize(explicit_length); options.SetNeedsZeroTermination(has_explicit_length == false); - return ReadUTFBufferAndDumpToStream (options); + options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); + return ReadStringAndDumpToStream (options); } else if (is_inline) { uint64_t location = valobj_addr + 2*ptr_size; if (!has_explicit_length) location++; - return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length); + ReadStringAndDumpToStreamOptions options(valobj); + options.SetLocation(location); + options.SetProcessSP(process_sp); + options.SetStream(&stream); + options.SetPrefixToken('@'); + options.SetSourceSize(explicit_length); + options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); + return ReadStringAndDumpToStream(options); } else { @@ -1209,16 +984,19 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& return false; if (has_explicit_length && !has_null) explicit_length++; // account for the fact that there is no NULL and we need to have one added - return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length); + ReadStringAndDumpToStreamOptions options(valobj); + options.SetLocation(location); + options.SetProcessSP(process_sp); + options.SetPrefixToken('@'); + options.SetStream(&stream); + options.SetSourceSize(explicit_length); + options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); + return ReadStringAndDumpToStream(options); } - - stream.Printf("class name = %s",class_name); - return true; - } bool -lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { TargetSP target_sp(valobj.GetTargetSP()); if (!target_sp) @@ -1241,38 +1019,38 @@ lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type)); child_sp->GetValueAsUnsigned(0); if (child_sp) - return NSStringSummaryProvider(*child_sp, stream); + return NSStringSummaryProvider(*child_sp, stream, options); return false; } bool -lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { - return NSAttributedStringSummaryProvider(valobj, stream); + return NSAttributedStringSummaryProvider(valobj, stream, options); } bool -lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { stream.Printf("%s",valobj.GetObjectDescription()); return true; } bool -lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { const uint32_t type_info = valobj.GetClangType().GetTypeInfo(); ValueObjectSP real_guy_sp = valobj.GetSP(); - if (type_info & ClangASTType::eTypeIsPointer) + if (type_info & eTypeIsPointer) { Error err; real_guy_sp = valobj.Dereference(err); if (err.Fail() || !real_guy_sp) return false; } - else if (type_info & ClangASTType::eTypeIsReference) + else if (type_info & eTypeIsReference) { real_guy_sp = valobj.GetChildAtIndex(0, true); if (!real_guy_sp) @@ -1290,7 +1068,7 @@ lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& template bool -lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { lldb::ValueObjectSP valobj_sp; @@ -1398,7 +1176,7 @@ lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update() return false; Error err; m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - m_item_sp = ValueObject::CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType()); + m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType()); if (err.Fail()) m_item_sp.reset(); return false; @@ -1437,13 +1215,13 @@ lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSynthe } template bool -lldb_private::formatters::NSDataSummaryProvider (ValueObject&, Stream&) ; +lldb_private::formatters::NSDataSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; template bool -lldb_private::formatters::NSDataSummaryProvider (ValueObject&, Stream&) ; +lldb_private::formatters::NSDataSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; template bool -lldb_private::formatters::ObjCSELSummaryProvider (ValueObject&, Stream&) ; +lldb_private::formatters::ObjCSELSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; template bool -lldb_private::formatters::ObjCSELSummaryProvider (ValueObject&, Stream&) ; +lldb_private::formatters::ObjCSELSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; diff --git a/source/DataFormatters/Cocoa.cpp b/source/DataFormatters/Cocoa.cpp index 8e92de4ddaa4..137fd4f483cc 100644 --- a/source/DataFormatters/Cocoa.cpp +++ b/source/DataFormatters/Cocoa.cpp @@ -26,7 +26,7 @@ using namespace lldb_private; using namespace lldb_private::formatters; bool -lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -60,7 +60,7 @@ lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID), true)); StreamString summary_stream; - bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream); + bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options); if (was_nsstring_ok && summary_stream.GetSize() > 0) { stream.Printf("%s",summary_stream.GetData()); @@ -73,7 +73,7 @@ lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& } bool -lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -106,7 +106,7 @@ lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream uint64_t offset = ptr_size; ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetClangType(), true)); StreamString summary_stream; - bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream); + bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options); if (was_nsstring_ok && summary_stream.GetSize() > 0) { stream.Printf("%s",summary_stream.GetData()); @@ -117,7 +117,7 @@ lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream } bool -lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -150,7 +150,7 @@ lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, St uint64_t offset = ptr_size; ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetClangType(), true)); StreamString summary_stream; - bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream); + bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options); if (was_nsstring_ok && summary_stream.GetSize() > 0) { stream.Printf("%s",summary_stream.GetData()); @@ -163,7 +163,7 @@ lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, St } bool -lldb_private::formatters::NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -212,7 +212,7 @@ lldb_private::formatters::NSMachPortSummaryProvider (ValueObject& valobj, Stream } bool -lldb_private::formatters::NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -290,7 +290,7 @@ lldb_private::formatters::NSIndexSetSummaryProvider (ValueObject& valobj, Stream } bool -lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -413,7 +413,7 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& } bool -lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -453,7 +453,7 @@ lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& str if (text->GetValueAsUnsigned(0) == 0) return false; StreamString summary; - if (!NSStringSummaryProvider(*text, summary)) + if (!NSStringSummaryProvider(*text, summary, options)) return false; if (base && base->GetValueAsUnsigned(0)) { @@ -461,7 +461,7 @@ lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& str summary.GetString().resize(summary.GetSize()-1); summary.Printf(" -- "); StreamString base_summary; - if (NSURLSummaryProvider(*base, base_summary) && base_summary.GetSize() > 0) + if (NSURLSummaryProvider(*base, base_summary, options) && base_summary.GetSize() > 0) summary.Printf("%s",base_summary.GetSize() > 2 ? base_summary.GetData() + 2 : base_summary.GetData()); } if (summary.GetSize()) @@ -478,7 +478,7 @@ lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& str } bool -lldb_private::formatters::NSDateSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::NSDateSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -552,7 +552,7 @@ lldb_private::formatters::NSDateSummaryProvider (ValueObject& valobj, Stream& st // vendor decides to get creative time_t epoch = GetOSXEpoch(); epoch = epoch + (time_t)date_value; - tm *tm_date = localtime(&epoch); + tm *tm_date = gmtime(&epoch); if (!tm_date) return false; std::string buffer(1024,0); diff --git a/source/DataFormatters/DataVisualization.cpp b/source/DataFormatters/DataVisualization.cpp index c2c2206f3449..7ef0be50efe0 100644 --- a/source/DataFormatters/DataVisualization.cpp +++ b/source/DataFormatters/DataVisualization.cpp @@ -101,6 +101,18 @@ DataVisualization::GetSyntheticForType (lldb::TypeNameSpecifierImplSP type_sp) } #endif +lldb::TypeValidatorImplSP +DataVisualization::GetValidator (ValueObject& valobj, lldb::DynamicValueType use_dynamic) +{ + return GetFormatManager().GetValidator(valobj, use_dynamic); +} + +lldb::TypeValidatorImplSP +DataVisualization::GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp) +{ + return GetFormatManager().GetValidatorForType(type_sp); +} + bool DataVisualization::AnyMatches (ConstString type_name, TypeCategoryImpl::FormatCategoryItems items, @@ -183,6 +195,18 @@ DataVisualization::Categories::Disable (const lldb::TypeCategoryImplSP& category GetFormatManager().DisableCategory(category); } +void +DataVisualization::Categories::EnableStar () +{ + GetFormatManager().EnableAllCategories (); +} + +void +DataVisualization::Categories::DisableStar () +{ + GetFormatManager().DisableAllCategories(); +} + void DataVisualization::Categories::LoopThrough (FormatManager::CategoryCallback callback, void* callback_baton) { diff --git a/source/DataFormatters/FormatCache.cpp b/source/DataFormatters/FormatCache.cpp index 3721f182f91e..aaa4bc1f958a 100644 --- a/source/DataFormatters/FormatCache.cpp +++ b/source/DataFormatters/FormatCache.cpp @@ -25,16 +25,20 @@ FormatCache::Entry::Entry () : m_format_cached(false), m_summary_cached(false), m_synthetic_cached(false), +m_validator_cached(false), m_format_sp(), m_summary_sp(), -m_synthetic_sp() +m_synthetic_sp(), +m_validator_sp() {} FormatCache::Entry::Entry (lldb::TypeFormatImplSP format_sp) : m_summary_cached(false), m_synthetic_cached(false), +m_validator_cached(false), m_summary_sp(), -m_synthetic_sp() +m_synthetic_sp(), +m_validator_sp() { SetFormat (format_sp); } @@ -42,8 +46,10 @@ m_synthetic_sp() FormatCache::Entry::Entry (lldb::TypeSummaryImplSP summary_sp) : m_format_cached(false), m_synthetic_cached(false), +m_validator_cached(false), m_format_sp(), -m_synthetic_sp() +m_synthetic_sp(), +m_validator_sp() { SetSummary (summary_sp); } @@ -51,17 +57,31 @@ m_synthetic_sp() FormatCache::Entry::Entry (lldb::SyntheticChildrenSP synthetic_sp) : m_format_cached(false), m_summary_cached(false), +m_validator_cached(false), m_format_sp(), -m_summary_sp() +m_summary_sp(), +m_validator_sp() { SetSynthetic (synthetic_sp); } -FormatCache::Entry::Entry (lldb::TypeFormatImplSP format_sp, lldb::TypeSummaryImplSP summary_sp, lldb::SyntheticChildrenSP synthetic_sp) +FormatCache::Entry::Entry (lldb::TypeValidatorImplSP validator_sp) : +m_format_cached(false), +m_summary_cached(false), +m_synthetic_cached(false), +m_format_sp(), +m_summary_sp(), +m_synthetic_sp() +{ + SetValidator (validator_sp); +} + +FormatCache::Entry::Entry (lldb::TypeFormatImplSP format_sp, lldb::TypeSummaryImplSP summary_sp, lldb::SyntheticChildrenSP synthetic_sp, lldb::TypeValidatorImplSP validator_sp) { SetFormat (format_sp); SetSummary (summary_sp); SetSynthetic (synthetic_sp); + SetValidator (validator_sp); } bool @@ -82,6 +102,12 @@ FormatCache::Entry::IsSyntheticCached () return m_synthetic_cached; } +bool +FormatCache::Entry::IsValidatorCached () +{ + return m_validator_cached; +} + lldb::TypeFormatImplSP FormatCache::Entry::GetFormat () { @@ -100,6 +126,12 @@ FormatCache::Entry::GetSynthetic () return m_synthetic_sp; } +lldb::TypeValidatorImplSP +FormatCache::Entry::GetValidator () +{ + return m_validator_sp; +} + void FormatCache::Entry::SetFormat (lldb::TypeFormatImplSP format_sp) { @@ -121,6 +153,13 @@ FormatCache::Entry::SetSynthetic (lldb::SyntheticChildrenSP synthetic_sp) m_synthetic_sp = synthetic_sp; } +void +FormatCache::Entry::SetValidator (lldb::TypeValidatorImplSP validator_sp) +{ + m_validator_cached = true; + m_validator_sp = validator_sp; +} + FormatCache::FormatCache () : m_map(), m_mutex (Mutex::eMutexTypeRecursive) @@ -201,6 +240,26 @@ FormatCache::GetSynthetic (const ConstString& type,lldb::SyntheticChildrenSP& sy return false; } +bool +FormatCache::GetValidator (const ConstString& type,lldb::TypeValidatorImplSP& validator_sp) +{ + Mutex::Locker lock(m_mutex); + auto entry = GetEntry(type); + if (entry.IsValidatorCached()) + { +#ifdef LLDB_CONFIGURATION_DEBUG + m_cache_hits++; +#endif + validator_sp = entry.GetValidator(); + return true; + } +#ifdef LLDB_CONFIGURATION_DEBUG + m_cache_misses++; +#endif + validator_sp.reset(); + return false; +} + void FormatCache::SetFormat (const ConstString& type,lldb::TypeFormatImplSP& format_sp) { @@ -222,6 +281,13 @@ FormatCache::SetSynthetic (const ConstString& type,lldb::SyntheticChildrenSP& sy GetEntry(type).SetSynthetic(synthetic_sp); } +void +FormatCache::SetValidator (const ConstString& type,lldb::TypeValidatorImplSP& validator_sp) +{ + Mutex::Locker lock(m_mutex); + GetEntry(type).SetValidator(validator_sp); +} + void FormatCache::Clear () { diff --git a/source/DataFormatters/FormatManager.cpp b/source/DataFormatters/FormatManager.cpp index 28d108f2410a..01799cef5e4e 100644 --- a/source/DataFormatters/FormatManager.cpp +++ b/source/DataFormatters/FormatManager.cpp @@ -447,6 +447,32 @@ FormatManager::GetSyntheticChildrenForType (lldb::TypeNameSpecifierImplSP type_s } #endif +lldb::TypeValidatorImplSP +FormatManager::GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp) +{ + if (!type_sp) + return lldb::TypeValidatorImplSP(); + lldb::TypeValidatorImplSP validator_chosen_sp; + uint32_t num_categories = m_categories_map.GetCount(); + lldb::TypeCategoryImplSP category_sp; + uint32_t prio_category = UINT32_MAX; + for (uint32_t category_id = 0; + category_id < num_categories; + category_id++) + { + category_sp = GetCategoryAtIndex(category_id); + if (category_sp->IsEnabled() == false) + continue; + lldb::TypeValidatorImplSP validator_current_sp(category_sp->GetValidatorForType(type_sp).get()); + if (validator_current_sp && (validator_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition()))) + { + prio_category = category_sp->GetEnabledPosition(); + validator_chosen_sp = validator_current_sp; + } + } + return validator_chosen_sp; +} + lldb::TypeCategoryImplSP FormatManager::GetCategory (const ConstString& category_name, bool can_create) @@ -501,10 +527,9 @@ FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj) if (valobj.GetTargetSP().get() && valobj.GetTargetSP()->GetDebugger().GetAutoOneLineSummaries() == false) return false; // then don't oneline - // if this object has a summary, don't try to do anything special to it - // if the user wants one-liner, they can ask for it in summary :) + // if this object has a summary, then ask the summary if (valobj.GetSummaryFormat().get() != nullptr) - return false; + return valobj.GetSummaryFormat()->IsOneLiner(); // no children, no party if (valobj.GetNumChildren() == 0) @@ -516,6 +541,7 @@ FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj) idx < valobj.GetNumChildren(); idx++) { + bool is_synth_val = false; ValueObjectSP child_sp(valobj.GetChildAtIndex(idx, true)); // something is wrong here - bail out if (!child_sp) @@ -523,7 +549,17 @@ FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj) // if we decided to define synthetic children for a type, we probably care enough // to show them, but avoid nesting children in children if (child_sp->GetSyntheticChildren().get() != nullptr) - return false; + { + ValueObjectSP synth_sp(child_sp->GetSyntheticValue()); + // wait.. wat? just get out of here.. + if (!synth_sp) + return false; + // but if we only have them to provide a value, keep going + if (synth_sp->MightHaveChildren() == false && synth_sp->DoesProvideSyntheticValue()) + is_synth_val = true; + else + return false; + } total_children_name_len += child_sp->GetName().GetLength(); @@ -547,7 +583,7 @@ FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj) // ...and no summary... // (if it had a summary and the summary wanted children, we would have bailed out anyway // so this only makes us bail out if this has no summary and we would then print children) - if (!child_sp->GetSummaryFormat()) + if (!child_sp->GetSummaryFormat() && !is_synth_val) // but again only do that if not a synthetic valued child return false; // then bail out } } @@ -756,6 +792,63 @@ FormatManager::GetSyntheticChildren (ValueObject& valobj, } #endif +lldb::TypeValidatorImplSP +FormatManager::GetValidator (ValueObject& valobj, + lldb::DynamicValueType use_dynamic) +{ + TypeValidatorImplSP retval; + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); + ConstString valobj_type(GetTypeForCache(valobj, use_dynamic)); + if (valobj_type) + { + if (log) + log->Printf("\n\n[FormatManager::GetValidator] Looking into cache for type %s", valobj_type.AsCString("")); + if (m_format_cache.GetValidator(valobj_type,retval)) + { + if (log) + { + log->Printf("[FormatManager::GetValidator] Cache search success. Returning."); + if (log->GetDebug()) + log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); + } + return retval; + } + if (log) + log->Printf("[FormatManager::GetValidator] Cache search failed. Going normal route"); + } + retval = m_categories_map.GetValidator(valobj, use_dynamic); + if (!retval) + { + if (log) + log->Printf("[FormatManager::GetValidator] Search failed. Giving hardcoded a chance."); + retval = GetHardcodedValidator(valobj, use_dynamic); + } + else if (valobj_type) + { + if (log) + log->Printf("[FormatManager::GetValidator] Caching %p for type %s", + static_cast(retval.get()), + valobj_type.AsCString("")); + m_format_cache.SetValidator(valobj_type,retval); + } + if (log && log->GetDebug()) + log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); + return retval; +} + +lldb::TypeValidatorImplSP +FormatManager::GetHardcodedValidator (ValueObject& valobj, + lldb::DynamicValueType use_dynamic) +{ + for (const auto& candidate: m_hardcoded_validators) + { + auto result = candidate(valobj,use_dynamic,*this); + if (result) + return result; + } + return nullptr; +} + FormatManager::FormatManager() : m_format_cache(), m_named_summaries_map(this), @@ -773,7 +866,8 @@ FormatManager::FormatManager() : m_appkit_category_name(ConstString("AppKit")), m_hardcoded_formats(), m_hardcoded_summaries(), - m_hardcoded_synthetics() + m_hardcoded_synthetics(), + m_hardcoded_validators() { LoadSystemFormatters(); @@ -825,6 +919,21 @@ AddStringSummary(TypeCategoryImpl::SharedPointer category_sp, category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp); } +static void +AddOneLineSummary (TypeCategoryImpl::SharedPointer category_sp, + ConstString type_name, + TypeSummaryImpl::Flags flags, + bool regex = false) +{ + flags.SetShowMembersOneLiner(true); + lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags, "")); + + if (regex) + category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp); + else + category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp); +} + #ifndef LLDB_DISABLE_PYTHON static void AddCXXSummary (TypeCategoryImpl::SharedPointer category_sp, @@ -945,13 +1054,6 @@ FormatManager::LoadLibStdcppFormatters() AddCXXSynthetic(gnu_category_sp, lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true); AddCXXSynthetic(gnu_category_sp, lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true); - - gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::vector >"), - TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); - - gnu_category_sp->GetTypeSyntheticsContainer()->Add(ConstString("std::vector >"), - SyntheticChildrenSP(new CXXSyntheticChildren(stl_synth_flags,"libc++ std::vector synthetic children",lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator))); - #endif } @@ -998,6 +1100,7 @@ FormatManager::LoadLibcxxFormatters() AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multiset synthetic children", ConstString("^std::__1::multiset<.+> >(( )?&)?$"), stl_synth_flags, true); AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multimap synthetic children", ConstString("^std::__1::multimap<.+> >(( )?&)?$"), stl_synth_flags, true); AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator, "libc++ std::unordered containers synthetic children", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_synth_flags, true); + AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator, "libc++ std::initializer_list synthetic children", ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags, true); libcxx_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)deque<.+>(( )?&)?$")), SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags, @@ -1124,6 +1227,10 @@ FormatManager::LoadObjCFormatters() .SetHideItemNames(false); TypeCategoryImpl::SharedPointer objc_category_sp = GetCategory(m_objc_category_name); + TypeCategoryImpl::SharedPointer appkit_category_sp = GetCategory(m_appkit_category_name); + TypeCategoryImpl::SharedPointer corefoundation_category_sp = GetCategory(m_corefoundation_category_name); + TypeCategoryImpl::SharedPointer coregraphics_category_sp = GetCategory(m_coregraphics_category_name); + TypeCategoryImpl::SharedPointer coreservices_category_sp = GetCategory(m_coreservices_category_name); lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat(objc_flags, lldb_private::formatters::ObjCBOOLSummaryProvider,"")); objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL"), @@ -1159,8 +1266,6 @@ FormatManager::LoadObjCFormatters() ConstString("__block_literal_generic"), objc_flags); - TypeCategoryImpl::SharedPointer corefoundation_category_sp = GetCategory(m_corefoundation_category_name); - AddStringSummary(corefoundation_category_sp, "${var.years} years, ${var.months} months, ${var.days} days, ${var.hours} hours, ${var.minutes} minutes ${var.seconds} seconds", ConstString("CFGregorianUnits"), @@ -1169,43 +1274,35 @@ FormatManager::LoadObjCFormatters() "location=${var.location} length=${var.length}", ConstString("CFRange"), objc_flags); - AddStringSummary(corefoundation_category_sp, - "(x=${var.x}, y=${var.y})", - ConstString("NSPoint"), - objc_flags); - AddStringSummary(corefoundation_category_sp, + + AddStringSummary(appkit_category_sp, "location=${var.location}, length=${var.length}", ConstString("NSRange"), objc_flags); - AddStringSummary(corefoundation_category_sp, - "${var.origin}, ${var.size}", - ConstString("NSRect"), - objc_flags); - AddStringSummary(corefoundation_category_sp, + AddStringSummary(appkit_category_sp, "(${var.origin}, ${var.size}), ...", ConstString("NSRectArray"), objc_flags); - AddStringSummary(objc_category_sp, - "(width=${var.width}, height=${var.height})", - ConstString("NSSize"), - objc_flags); - - TypeCategoryImpl::SharedPointer coregraphics_category_sp = GetCategory(m_coregraphics_category_name); - - AddStringSummary(coregraphics_category_sp, - "(width=${var.width}, height=${var.height})", - ConstString("CGSize"), - objc_flags); - AddStringSummary(coregraphics_category_sp, - "(x=${var.x}, y=${var.y})", - ConstString("CGPoint"), - objc_flags); - AddStringSummary(coregraphics_category_sp, - "origin=${var.origin} size=${var.size}", - ConstString("CGRect"), - objc_flags); - TypeCategoryImpl::SharedPointer coreservices_category_sp = GetCategory(m_coreservices_category_name); + AddOneLineSummary (appkit_category_sp, + ConstString("NSPoint"), + objc_flags); + AddOneLineSummary (appkit_category_sp, + ConstString("NSSize"), + objc_flags); + AddOneLineSummary (appkit_category_sp, + ConstString("NSRect"), + objc_flags); + + AddOneLineSummary (coregraphics_category_sp, + ConstString("CGSize"), + objc_flags); + AddOneLineSummary (coregraphics_category_sp, + ConstString("CGPoint"), + objc_flags); + AddOneLineSummary (coregraphics_category_sp, + ConstString("CGRect"), + objc_flags); AddStringSummary(coreservices_category_sp, "red=${var.red} green=${var.green} blue=${var.blue}", @@ -1236,8 +1333,6 @@ FormatManager::LoadObjCFormatters() ConstString("HIRect"), objc_flags); - TypeCategoryImpl::SharedPointer appkit_category_sp = GetCategory(m_appkit_category_name); - TypeSummaryImpl::Flags appkit_flags; appkit_flags.SetCascades(true) .SetSkipPointers(false) @@ -1307,6 +1402,8 @@ FormatManager::LoadObjCFormatters() AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSOrderedSet synthetic children", ConstString("NSOrderedSet"), ScriptedSyntheticChildren::Flags()); AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"), ScriptedSyntheticChildren::Flags()); AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"), ScriptedSyntheticChildren::Flags()); + + AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator, "NSIndexPath synthetic children", ConstString("NSIndexPath"), ScriptedSyntheticChildren::Flags()); AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFBagRef"), appkit_flags); AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("__CFBag"), appkit_flags); @@ -1471,8 +1568,22 @@ FormatManager::LoadHardcodedFormatters() } { // insert code to load summaries here + m_hardcoded_summaries.push_back( + [](lldb_private::ValueObject& valobj, + lldb::DynamicValueType, + FormatManager&) -> TypeSummaryImpl::SharedPointer { + static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags(), lldb_private::formatters::FunctionPointerSummaryProvider, "Function pointer summary provider")); + if (valobj.GetClangType().IsFunctionPointerType()) + { + return formatter_sp; + } + return nullptr; + }); } { // insert code to load synthetics here } + { + // insert code to load validators here + } } diff --git a/source/DataFormatters/LibCxx.cpp b/source/DataFormatters/LibCxx.cpp index 174202661f03..26bbcf91242f 100644 --- a/source/DataFormatters/LibCxx.cpp +++ b/source/DataFormatters/LibCxx.cpp @@ -27,7 +27,7 @@ using namespace lldb_private; using namespace lldb_private::formatters; bool -lldb_private::formatters::LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue()); if (!valobj_sp) @@ -143,7 +143,7 @@ lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (si if (bit_set && buffer_sp && buffer_sp->GetBytes()) *(buffer_sp->GetBytes()) = 1; // regardless of endianness, anything non-zero is true StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx); - ValueObjectSP retval_sp(ValueObject::CreateValueObjectFromData(name.GetData(), DataExtractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()), m_exe_ctx_ref, m_bool_type)); + ValueObjectSP retval_sp(CreateValueObjectFromData(name.GetData(), DataExtractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()), m_exe_ctx_ref, m_bool_type)); if (retval_sp) m_children[idx] = retval_sp; return retval_sp; @@ -378,7 +378,7 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex (siz 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 = ValueObject::CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_owners_sp->GetClangType()); + m_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_owners_sp->GetClangType()); } return m_count_sp; } @@ -391,7 +391,7 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex (siz 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 = ValueObject::CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_weak_owners_sp->GetClangType()); + m_weak_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_weak_owners_sp->GetClangType()); } return m_weak_count_sp; } @@ -450,111 +450,8 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticC return (new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)); } -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : - SyntheticChildrenFrontEnd(*valobj_sp.get()), - m_start(NULL), - m_finish(NULL), - m_element_type(), - m_element_size(0), - m_children() -{ - if (valobj_sp) - Update(); -} - -size_t -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren () -{ - if (!m_start || !m_finish) - return 0; - uint64_t start_val = m_start->GetValueAsUnsigned(0); - uint64_t finish_val = m_finish->GetValueAsUnsigned(0); - - if (start_val == 0 || finish_val == 0) - return 0; - - if (start_val >= finish_val) - return 0; - - size_t num_children = (finish_val - start_val); - if (num_children % m_element_size) - return 0; - return num_children/m_element_size; -} - -lldb::ValueObjectSP -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - if (!m_start || !m_finish) - return lldb::ValueObjectSP(); - - auto cached = m_children.find(idx); - if (cached != m_children.end()) - return cached->second; - - uint64_t offset = idx * m_element_size; - offset = offset + m_start->GetValueAsUnsigned(0); - StreamString name; - name.Printf("[%" PRIu64 "]", (uint64_t)idx); - ValueObjectSP child_sp = ValueObject::CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type); - m_children[idx] = child_sp; - return child_sp; -} - -bool -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() -{ - m_start = m_finish = NULL; - m_children.clear(); - ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true)); - if (!data_type_finder_sp) - return false; - data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true); - if (!data_type_finder_sp) - return false; - m_element_type = data_type_finder_sp->GetClangType().GetPointeeType(); - m_element_size = m_element_type.GetByteSize(); - - if (m_element_size > 0) - { - // store raw pointers or end up with a circular dependency - m_start = m_backend.GetChildMemberWithName(ConstString("__begin_"),true).get(); - m_finish = m_backend.GetChildMemberWithName(ConstString("__end_"),true).get(); - } - return false; -} - -bool -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - if (!m_start || !m_finish) - return UINT32_MAX; - return ExtractIndexFromString(name.GetCString()); -} - -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd () -{ - // these need to stay around because they are child objects who will follow their parent's life cycle - // delete m_start; - // delete m_finish; -} - -SyntheticChildrenFrontEnd* -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - if (!valobj_sp) - return NULL; - return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp)); -} - bool -lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { if (valobj.IsPointerType()) { diff --git a/source/DataFormatters/LibCxxInitializerList.cpp b/source/DataFormatters/LibCxxInitializerList.cpp new file mode 100644 index 000000000000..e76b0bec95ce --- /dev/null +++ b/source/DataFormatters/LibCxxInitializerList.cpp @@ -0,0 +1,145 @@ +//===-- LibCxxInitializerList.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/lldb-python.h" + +#include "lldb/DataFormatters/CXXFormatterFunctions.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/ValueObject.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +namespace lldb_private { + namespace formatters { + class LibcxxInitializerListSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~LibcxxInitializerListSyntheticFrontEnd (); + private: + ValueObject* m_start; + ClangASTType m_element_type; + uint32_t m_element_size; + size_t m_num_elements; + std::map m_children; + }; + } +} + +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_start(NULL), +m_element_type(), +m_element_size(0), +m_num_elements(0), +m_children() +{ + if (valobj_sp) + Update(); +} + +size_t +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::CalculateNumChildren () +{ + static ConstString g___size_("__size_"); + m_num_elements = 0; + ValueObjectSP size_sp(m_backend.GetChildMemberWithName(g___size_, true)); + if (size_sp) + m_num_elements = size_sp->GetValueAsUnsigned(0); + return m_num_elements; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ + if (!m_start) + return lldb::ValueObjectSP(); + + auto cached = m_children.find(idx); + if (cached != m_children.end()) + return cached->second; + + uint64_t offset = idx * m_element_size; + offset = offset + m_start->GetValueAsUnsigned(0); + StreamString name; + name.Printf("[%" PRIu64 "]", (uint64_t)idx); + ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type); + m_children[idx] = child_sp; + return child_sp; +} + +bool +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::Update() +{ + static ConstString g___begin_("__begin_"); + + m_start = nullptr; + m_num_elements = 0; + m_children.clear(); + lldb::TemplateArgumentKind kind; + m_element_type = m_backend.GetClangType().GetTemplateArgument(0, kind); + if (kind != lldb::eTemplateArgumentKindType || false == m_element_type.IsValid()) + return false; + + m_element_size = m_element_type.GetByteSize(); + + if (m_element_size > 0) + m_start = m_backend.GetChildMemberWithName(g___begin_,true).get(); // store raw pointers or end up with a circular dependency + + return false; +} + +bool +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::MightHaveChildren () +{ + return true; +} + +size_t +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ + if (!m_start) + return UINT32_MAX; + return ExtractIndexFromString(name.GetCString()); +} + +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::~LibcxxInitializerListSyntheticFrontEnd () +{ + // this needs to stay around because it's a child object who will follow its parent's life cycle + // delete m_start; +} + +lldb_private::SyntheticChildrenFrontEnd* +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ + if (!valobj_sp) + return NULL; + return (new LibcxxInitializerListSyntheticFrontEnd(valobj_sp)); +} + diff --git a/source/DataFormatters/LibCxxList.cpp b/source/DataFormatters/LibCxxList.cpp index 7d6db1a0ccd4..5bb6ce07480f 100644 --- a/source/DataFormatters/LibCxxList.cpp +++ b/source/DataFormatters/LibCxxList.cpp @@ -25,6 +25,47 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; +namespace lldb_private { + namespace formatters { + class LibcxxStdListSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~LibcxxStdListSyntheticFrontEnd (); + private: + bool + HasLoop(size_t); + + size_t m_list_capping_size; + static const bool g_use_loop_detect = true; + size_t m_loop_detected; + lldb::addr_t m_node_address; + ValueObject* m_head; + ValueObject* m_tail; + ClangASTType m_element_type; + size_t m_count; + std::map m_children; + }; + } +} + class ListEntry { public: @@ -150,6 +191,7 @@ private: lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp.get()), m_list_capping_size(0), +m_loop_detected(0), m_node_address(), m_head(NULL), m_tail(NULL), @@ -162,14 +204,15 @@ m_children() } bool -lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop() +lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop(size_t count) { if (g_use_loop_detect == false) return false; // don't bother checking for a loop if we won't actually need to jump nodes if (m_count < 2) return false; - auto steps_left = m_count; + auto steps_left = std::min(count,m_count); + auto steps_left_save = steps_left; ListEntry slow(m_head); ListEntry fast(m_head); while (steps_left-- > 0) @@ -185,6 +228,7 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop() if (slow == fast) return true; } + m_loop_detected = steps_left_save; return false; } @@ -206,9 +250,7 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::CalculateNumChildren ( } if (m_count != UINT32_MAX) { - if (!HasLoop()) - return m_count; - return m_count = 0; + return m_count; } else { @@ -220,8 +262,6 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::CalculateNumChildren ( return 0; if (next_val == prev_val) return 1; - if (HasLoop()) - return 0; uint64_t size = 2; ListEntry current(m_head); while (current.next() && current.next().value() != m_node_address) @@ -248,6 +288,10 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (size_ if (cached != m_children.end()) return cached->second; + if (m_loop_detected <= idx) + if (HasLoop(idx)) + return lldb::ValueObjectSP(); + ListIterator current(m_head); ValueObjectSP current_sp(current.advance(idx)); if (!current_sp) @@ -264,7 +308,7 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (size_ StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx); - return (m_children[idx] = ValueObject::CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type)); + return (m_children[idx] = CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type)); } bool @@ -273,6 +317,7 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update() m_head = m_tail = NULL; m_node_address = 0; m_count = UINT32_MAX; + m_loop_detected = false; Error err; ValueObjectSP backend_addr(m_backend.AddressOf(err)); m_list_capping_size = 0; diff --git a/source/DataFormatters/LibCxxMap.cpp b/source/DataFormatters/LibCxxMap.cpp index e665f29622d8..82e747e2db08 100644 --- a/source/DataFormatters/LibCxxMap.cpp +++ b/source/DataFormatters/LibCxxMap.cpp @@ -25,40 +25,84 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; +namespace lldb_private { + namespace formatters { + class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~LibcxxStdMapSyntheticFrontEnd (); + private: + bool + GetDataType(); + + void + GetValueOffset (const lldb::ValueObjectSP& node); + + ValueObject* m_tree; + ValueObject* m_root_node; + ClangASTType m_element_type; + uint32_t m_skip_size; + size_t m_count; + std::map m_children; + }; + } +} + class MapEntry { public: MapEntry () {} - MapEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {} + explicit MapEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {} MapEntry (const MapEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {} - MapEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {} + explicit MapEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {} ValueObjectSP - left () + left () const { + static ConstString g_left("__left_"); if (!m_entry_sp) return m_entry_sp; - return m_entry_sp->GetChildMemberWithName(ConstString("__left_"), true); + return m_entry_sp->GetChildMemberWithName(g_left, true); } ValueObjectSP - right () + right () const { + static ConstString g_right("__right_"); if (!m_entry_sp) return m_entry_sp; - return m_entry_sp->GetChildMemberWithName(ConstString("__right_"), true); + return m_entry_sp->GetChildMemberWithName(g_right, true); } ValueObjectSP - parent () + parent () const { + static ConstString g_parent("__parent_"); if (!m_entry_sp) return m_entry_sp; - return m_entry_sp->GetChildMemberWithName(ConstString("__parent_"), true); + return m_entry_sp->GetChildMemberWithName(g_parent, true); } uint64_t - value () + value () const { if (!m_entry_sp) return 0; @@ -66,7 +110,7 @@ public: } bool - error () + error () const { if (!m_entry_sp) return true; @@ -74,13 +118,13 @@ public: } bool - null() + null() const { return (value() == 0); } ValueObjectSP - GetEntry () + GetEntry () const { return m_entry_sp; } @@ -119,27 +163,18 @@ public: ValueObjectSP advance (size_t count) { + ValueObjectSP fail(nullptr); if (m_error) - return lldb::ValueObjectSP(); - if (count == 0) - return m_entry.GetEntry(); - if (count == 1) - { - next (); - return m_entry.GetEntry(); - } + return fail; size_t steps = 0; while (count > 0) { - if (m_error) - return lldb::ValueObjectSP(); - next (); - count--; - if (m_entry.null()) - return lldb::ValueObjectSP(); - steps++; - if (steps > m_max_depth) - return lldb::ValueObjectSP(); + next(); + count--, steps++; + if (m_error || + m_entry.null() || + (steps > m_max_depth)) + return fail; } return m_entry.GetEntry(); } @@ -147,16 +182,39 @@ protected: void next () { - m_entry.SetEntry(increment(m_entry.GetEntry())); + if (m_entry.null()) + return; + MapEntry right(m_entry.right()); + if (right.null() == false) + { + m_entry = tree_min(std::move(right)); + return; + } + size_t steps = 0; + while (!is_left_child(m_entry)) + { + if (m_entry.error()) + { + m_error = true; + return; + } + m_entry.SetEntry(m_entry.parent()); + steps++; + if (steps > m_max_depth) + { + m_entry = MapEntry(); + return; + } + } + m_entry = MapEntry(m_entry.parent()); } private: - ValueObjectSP - tree_min (ValueObjectSP x_sp) + MapEntry + tree_min (MapEntry&& x) { - MapEntry x(x_sp); if (x.null()) - return ValueObjectSP(); + return MapEntry(); MapEntry left(x.left()); size_t steps = 0; while (left.null() == false) @@ -164,42 +222,20 @@ private: if (left.error()) { m_error = true; - return lldb::ValueObjectSP(); + return MapEntry(); } - x.SetEntry(left.GetEntry()); + x = left; left.SetEntry(x.left()); steps++; if (steps > m_max_depth) - return lldb::ValueObjectSP(); - } - return x.GetEntry(); - } - - ValueObjectSP - tree_max (ValueObjectSP x_sp) - { - MapEntry x(x_sp); - if (x.null()) - return ValueObjectSP(); - MapEntry right(x.right()); - size_t steps = 0; - while (right.null() == false) - { - if (right.error()) - return lldb::ValueObjectSP(); - x.SetEntry(right.GetEntry()); - right.SetEntry(x.right()); - steps++; - if (steps > m_max_depth) - return lldb::ValueObjectSP(); + return MapEntry(); } - return x.GetEntry(); + return x; } - + bool - is_left_child (ValueObjectSP x_sp) + is_left_child (const MapEntry& x) { - MapEntry x(x_sp); if (x.null()) return false; MapEntry rhs(x.parent()); @@ -207,31 +243,6 @@ private: return x.value() == rhs.value(); } - ValueObjectSP - increment (ValueObjectSP x_sp) - { - MapEntry node(x_sp); - if (node.null()) - return ValueObjectSP(); - MapEntry right(node.right()); - if (right.null() == false) - return tree_min(right.GetEntry()); - size_t steps = 0; - while (!is_left_child(node.GetEntry())) - { - if (node.error()) - { - m_error = true; - return lldb::ValueObjectSP(); - } - node.SetEntry(node.parent()); - steps++; - if (steps > m_max_depth) - return lldb::ValueObjectSP(); - } - return node.parent(); - } - MapEntry m_entry; size_t m_max_depth; bool m_error; @@ -302,6 +313,10 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset (const l lldb::ValueObjectSP lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t idx) { + static ConstString g___cc("__cc"); + static ConstString g___nc("__nc"); + + if (idx >= CalculateNumChildren()) return lldb::ValueObjectSP(); if (m_tree == NULL || m_root_node == NULL) @@ -375,7 +390,31 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t } StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx); - return (m_children[idx] = ValueObject::CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type)); + auto potential_child_sp = CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type); + if (potential_child_sp) + { + switch (potential_child_sp->GetNumChildren()) + { + case 1: + { + auto child0_sp = potential_child_sp->GetChildAtIndex(0, true); + if (child0_sp && child0_sp->GetName() == g___cc) + potential_child_sp = child0_sp; + break; + } + case 2: + { + auto child0_sp = potential_child_sp->GetChildAtIndex(0, true); + auto child1_sp = potential_child_sp->GetChildAtIndex(1, true); + if (child0_sp && child0_sp->GetName() == g___cc && + child1_sp && child1_sp->GetName() == g___nc) + potential_child_sp = child0_sp; + break; + } + } + potential_child_sp->SetName(ConstString(name.GetData())); + } + return (m_children[idx] = potential_child_sp); } bool diff --git a/source/DataFormatters/LibCxxUnorderedMap.cpp b/source/DataFormatters/LibCxxUnorderedMap.cpp index bf68f20955b5..da2a88966f5e 100644 --- a/source/DataFormatters/LibCxxUnorderedMap.cpp +++ b/source/DataFormatters/LibCxxUnorderedMap.cpp @@ -25,6 +25,41 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; +namespace lldb_private { + namespace formatters { + class LibcxxStdUnorderedMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~LibcxxStdUnorderedMapSyntheticFrontEnd (); + private: + + ValueObject* m_tree; + size_t m_num_elements; + ValueObject* m_next_element; + std::map m_children; + std::vector > m_elements_cache; + }; + } +} + lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp.get()), m_tree(NULL), diff --git a/source/DataFormatters/LibCxxVector.cpp b/source/DataFormatters/LibCxxVector.cpp new file mode 100644 index 000000000000..26c62afbed2b --- /dev/null +++ b/source/DataFormatters/LibCxxVector.cpp @@ -0,0 +1,157 @@ +//===-- LibCxxVector.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/lldb-python.h" + +#include "lldb/DataFormatters/CXXFormatterFunctions.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/ValueObject.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +namespace lldb_private { + namespace formatters { + class LibcxxStdVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~LibcxxStdVectorSyntheticFrontEnd (); + private: + ValueObject* m_start; + ValueObject* m_finish; + ClangASTType m_element_type; + uint32_t m_element_size; + std::map m_children; + }; + } +} + +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_start(NULL), +m_finish(NULL), +m_element_type(), +m_element_size(0), +m_children() +{ + if (valobj_sp) + Update(); +} + +size_t +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren () +{ + if (!m_start || !m_finish) + return 0; + uint64_t start_val = m_start->GetValueAsUnsigned(0); + uint64_t finish_val = m_finish->GetValueAsUnsigned(0); + + if (start_val == 0 || finish_val == 0) + return 0; + + if (start_val >= finish_val) + return 0; + + size_t num_children = (finish_val - start_val); + if (num_children % m_element_size) + return 0; + return num_children/m_element_size; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ + if (!m_start || !m_finish) + return lldb::ValueObjectSP(); + + auto cached = m_children.find(idx); + if (cached != m_children.end()) + return cached->second; + + uint64_t offset = idx * m_element_size; + offset = offset + m_start->GetValueAsUnsigned(0); + StreamString name; + name.Printf("[%" PRIu64 "]", (uint64_t)idx); + ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type); + m_children[idx] = child_sp; + return child_sp; +} + +bool +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() +{ + m_start = m_finish = NULL; + m_children.clear(); + ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true)); + if (!data_type_finder_sp) + return false; + data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true); + if (!data_type_finder_sp) + return false; + m_element_type = data_type_finder_sp->GetClangType().GetPointeeType(); + m_element_size = m_element_type.GetByteSize(); + + if (m_element_size > 0) + { + // store raw pointers or end up with a circular dependency + m_start = m_backend.GetChildMemberWithName(ConstString("__begin_"),true).get(); + m_finish = m_backend.GetChildMemberWithName(ConstString("__end_"),true).get(); + } + return false; +} + +bool +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren () +{ + return true; +} + +size_t +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ + if (!m_start || !m_finish) + return UINT32_MAX; + return ExtractIndexFromString(name.GetCString()); +} + +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd () +{ + // these need to stay around because they are child objects who will follow their parent's life cycle + // delete m_start; + // delete m_finish; +} + +lldb_private::SyntheticChildrenFrontEnd* +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ + if (!valobj_sp) + return NULL; + return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp)); +} + diff --git a/source/DataFormatters/LibStdcpp.cpp b/source/DataFormatters/LibStdcpp.cpp index f2d617323cca..b8f031ceeb2f 100644 --- a/source/DataFormatters/LibStdcpp.cpp +++ b/source/DataFormatters/LibStdcpp.cpp @@ -276,7 +276,7 @@ lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex if (m_pair_address != 0 && m_pair_type) { if (!m_pair_sp) - m_pair_sp = ValueObject::CreateValueObjectFromAddress("pair", m_pair_address, m_exe_ctx_ref, m_pair_type); + m_pair_sp = CreateValueObjectFromAddress("pair", m_pair_address, m_exe_ctx_ref, m_pair_type); if (m_pair_sp) return m_pair_sp->GetChildAtIndex(idx, true); } diff --git a/source/DataFormatters/NSArray.cpp b/source/DataFormatters/NSArray.cpp index 16635381f94f..e242155f4fef 100644 --- a/source/DataFormatters/NSArray.cpp +++ b/source/DataFormatters/NSArray.cpp @@ -228,7 +228,7 @@ namespace lldb_private { } bool -lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -341,10 +341,10 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx object_at_idx += (pyhs_idx * m_ptr_size); StreamString idx_name; idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); - lldb::ValueObjectSP retval_sp = ValueObject::CreateValueObjectFromAddress(idx_name.GetData(), - object_at_idx, - m_exe_ctx_ref, - m_id_type); + lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(), + object_at_idx, + m_exe_ctx_ref, + m_id_type); m_children.push_back(retval_sp); return retval_sp; } @@ -604,7 +604,10 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx return lldb::ValueObjectSP(); StreamString idx_name; idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); - lldb::ValueObjectSP retval_sp = ValueObject::CreateValueObjectFromAddress(idx_name.GetData(), object_at_idx, m_exe_ctx_ref, m_id_type); + lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(), + object_at_idx, + m_exe_ctx_ref, + m_id_type); m_children.push_back(retval_sp); return retval_sp; } @@ -624,7 +627,7 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCre ClangASTType valobj_type(valobj_sp->GetClangType()); Flags flags(valobj_type.GetTypeInfo()); - if (flags.IsClear(ClangASTType::eTypeIsPointer)) + if (flags.IsClear(eTypeIsPointer)) { Error error; valobj_sp = valobj_sp->AddressOf(error); diff --git a/source/DataFormatters/NSDictionary.cpp b/source/DataFormatters/NSDictionary.cpp index ddd1e2e7ca90..fdac05192c46 100644 --- a/source/DataFormatters/NSDictionary.cpp +++ b/source/DataFormatters/NSDictionary.cpp @@ -36,52 +36,167 @@ GetLLDBNSPairType (TargetSP target_sp) if (target_ast_context) { - clang::ASTContext *ast = target_ast_context->getASTContext(); + ConstString g___lldb_autogen_nspair("__lldb_autogen_nspair"); - if (ast) + clang_type = target_ast_context->GetTypeForIdentifier(g___lldb_autogen_nspair); + + if (!clang_type) { - const char* type_name = "__lldb_autogen_nspair"; + clang_type = target_ast_context->CreateRecordType(NULL, lldb::eAccessPublic, g___lldb_autogen_nspair.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC); - clang::IdentifierInfo &myIdent = ast->Idents.get(type_name); - clang::DeclarationName myName = ast->DeclarationNames.getIdentifier(&myIdent); - - clang::DeclContext::lookup_const_result result = ast->getTranslationUnitDecl()->lookup(myName); - - for (clang::NamedDecl *named_decl : result) - { - if (const clang::CXXRecordDecl *record_decl = llvm::dyn_cast(named_decl)) - { - clang_type.SetClangType(ast, clang::QualType(record_decl->getTypeForDecl(), 0)); - break; - } - else - { - // somebody else (the user?) has defined a type with the magic name already - fail!!! - return clang_type; - } - } - - if (!clang_type) + if (clang_type) { - clang_type = target_ast_context->CreateRecordType(NULL, lldb::eAccessPublic, type_name, clang::TTK_Struct, lldb::eLanguageTypeC); - - if (clang_type) - { - clang_type.StartTagDeclarationDefinition(); - ClangASTType id_clang_type = target_ast_context->GetBasicType (eBasicTypeObjCID); - clang_type.AddFieldToRecordType("key", id_clang_type, lldb::eAccessPublic, 0); - clang_type.AddFieldToRecordType("value", id_clang_type, lldb::eAccessPublic, 0); - clang_type.CompleteTagDeclarationDefinition(); - } + clang_type.StartTagDeclarationDefinition(); + ClangASTType id_clang_type = target_ast_context->GetBasicType (eBasicTypeObjCID); + clang_type.AddFieldToRecordType("key", id_clang_type, lldb::eAccessPublic, 0); + clang_type.AddFieldToRecordType("value", id_clang_type, lldb::eAccessPublic, 0); + clang_type.CompleteTagDeclarationDefinition(); } } } return clang_type; } +namespace lldb_private { + namespace formatters { + class NSDictionaryISyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + private: + struct DataDescriptor_32 + { + uint32_t _used : 26; + uint32_t _szidx : 6; + }; + struct DataDescriptor_64 + { + uint64_t _used : 58; + uint32_t _szidx : 6; + }; + + struct DictionaryItemDescriptor + { + lldb::addr_t key_ptr; + lldb::addr_t val_ptr; + lldb::ValueObjectSP valobj_sp; + }; + + public: + NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSDictionaryISyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + lldb::ByteOrder m_order; + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + lldb::addr_t m_data_ptr; + ClangASTType m_pair_type; + std::vector m_children; + }; + + class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + private: + struct DataDescriptor_32 + { + uint32_t _used : 26; + uint32_t _kvo : 1; + uint32_t _size; + uint32_t _mutations; + uint32_t _objs_addr; + uint32_t _keys_addr; + }; + struct DataDescriptor_64 + { + uint64_t _used : 58; + uint32_t _kvo : 1; + uint64_t _size; + uint64_t _mutations; + uint64_t _objs_addr; + uint64_t _keys_addr; + }; + struct DictionaryItemDescriptor + { + lldb::addr_t key_ptr; + lldb::addr_t val_ptr; + lldb::ValueObjectSP valobj_sp; + }; + public: + NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSDictionaryMSyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + lldb::ByteOrder m_order; + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + ClangASTType m_pair_type; + std::vector m_children; + }; + + class NSDictionaryCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSDictionaryCodeRunningSyntheticFrontEnd (); + }; + } +} + template bool -lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -407,7 +522,10 @@ lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (size_ StreamString idx_name; idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); DataExtractor data(buffer_sp, m_order, m_ptr_size); - dict_item.valobj_sp = ValueObject::CreateValueObjectFromData(idx_name.GetData(), data, m_exe_ctx_ref, m_pair_type); + dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(), + data, + m_exe_ctx_ref, + m_pair_type); } return dict_item.valobj_sp; } @@ -571,13 +689,16 @@ lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_ StreamString idx_name; idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); DataExtractor data(buffer_sp, m_order, m_ptr_size); - dict_item.valobj_sp = ValueObject::CreateValueObjectFromData(idx_name.GetData(), data, m_exe_ctx_ref, m_pair_type); + dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(), + data, + m_exe_ctx_ref, + m_pair_type); } return dict_item.valobj_sp; } template bool -lldb_private::formatters::NSDictionarySummaryProvider (ValueObject&, Stream&) ; +lldb_private::formatters::NSDictionarySummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; template bool -lldb_private::formatters::NSDictionarySummaryProvider (ValueObject&, Stream&) ; +lldb_private::formatters::NSDictionarySummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; diff --git a/source/DataFormatters/NSIndexPath.cpp b/source/DataFormatters/NSIndexPath.cpp new file mode 100644 index 000000000000..ee9583ef4cc1 --- /dev/null +++ b/source/DataFormatters/NSIndexPath.cpp @@ -0,0 +1,309 @@ +//===-- NSIndexPath.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/DataFormatters/CXXFormatterFunctions.h" + +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/TypeSynthetic.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Symbol/ClangASTContext.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +class NSIndexPathSyntheticFrontEnd : public SyntheticChildrenFrontEnd +{ +public: + NSIndexPathSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : + SyntheticChildrenFrontEnd (*valobj_sp.get()), + m_ptr_size(0), + m_ast_ctx(nullptr), + m_uint_star_type() + { + m_ptr_size = m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize(); + } + + virtual size_t + CalculateNumChildren () + { + return m_impl.GetNumIndexes(); + } + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx) + { + return m_impl.GetIndexAtIndex(idx, m_uint_star_type); + } + + virtual bool + Update() + { + m_impl.m_mode = Mode::Invalid; + + m_ast_ctx = ClangASTContext::GetASTContext(m_backend.GetClangType().GetASTContext()); + if (!m_ast_ctx) + return false; + + m_uint_star_type = m_ast_ctx->GetPointerSizedIntType(false); + + static ConstString g__indexes("_indexes"); + static ConstString g__length("_length"); + + ProcessSP process_sp = m_backend.GetProcessSP(); + if (!process_sp) + return false; + + ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); + + if (!runtime) + return false; + + ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(m_backend)); + + if (!descriptor.get() || !descriptor->IsValid()) + return false; + + uint64_t info_bits(0),value_bits(0),payload(0); + + if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits, &payload)) + { + m_impl.m_mode = Mode::Inlined; + m_impl.m_inlined.SetIndexes(payload, *process_sp); + } + else + { + ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _indexes_id; + ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _length_id; + + bool has_indexes(false),has_length(false); + + for (size_t x = 0; + x < descriptor->GetNumIVars(); + x++) + { + const auto& ivar = descriptor->GetIVarAtIndex(x); + if (ivar.m_name == g__indexes) + { + _indexes_id = ivar; + has_indexes = true; + } + else if (ivar.m_name == g__length) + { + _length_id = ivar; + has_length = true; + } + + if (has_length && has_indexes) + break; + } + + if (has_length && has_indexes) + { + m_impl.m_outsourced.m_indexes = m_backend.GetSyntheticChildAtOffset(_indexes_id.m_offset, + m_uint_star_type.GetPointerType(), + true).get(); + ValueObjectSP length_sp(m_backend.GetSyntheticChildAtOffset(_length_id.m_offset, + m_uint_star_type, + true)); + if (length_sp) + { + m_impl.m_outsourced.m_count = length_sp->GetValueAsUnsigned(0); + if (m_impl.m_outsourced.m_indexes) + m_impl.m_mode = Mode::Outsourced; + } + } + } + return false; + } + + virtual bool + MightHaveChildren () + { + if (m_impl.m_mode == Mode::Invalid) + return false; + return true; + } + + virtual size_t + GetIndexOfChildWithName (const ConstString &name) + { + const char* item_name = name.GetCString(); + uint32_t idx = ExtractIndexFromString(item_name); + if (idx < UINT32_MAX && idx >= CalculateNumChildren()) + return UINT32_MAX; + return idx; + } + + virtual lldb::ValueObjectSP + GetSyntheticValue () { return nullptr; } + + virtual + ~NSIndexPathSyntheticFrontEnd () {} + +protected: + ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp; + + enum class Mode { + Inlined, + Outsourced, + Invalid + }; + + struct Impl { + Mode m_mode; + + size_t + GetNumIndexes () + { + switch (m_mode) + { + case Mode::Inlined: + return m_inlined.GetNumIndexes(); + case Mode::Outsourced: + return m_outsourced.m_count; + default: + return 0; + } + } + + lldb::ValueObjectSP + GetIndexAtIndex (size_t idx, const ClangASTType& desired_type) + { + if (idx >= GetNumIndexes()) + return nullptr; + switch (m_mode) + { + default: return nullptr; + case Mode::Inlined: + return m_inlined.GetIndexAtIndex (idx, desired_type); + case Mode::Outsourced: + return m_outsourced.GetIndexAtIndex (idx); + } + } + + struct InlinedIndexes { + public: + void SetIndexes(uint64_t value, Process& p) + { + m_indexes = value; + _lengthForInlinePayload(p.GetAddressByteSize()); + m_process = &p; + } + + size_t + GetNumIndexes () + { + return m_count; + } + + lldb::ValueObjectSP + GetIndexAtIndex (size_t idx, const ClangASTType& desired_type) + { + std::pair value(_indexAtPositionForInlinePayload(idx)); + if (!value.second) + return nullptr; + Value v; + if (m_ptr_size == 8) + { + Scalar scalar( (unsigned long long)value.first ); + v = Value(scalar); + } + else + { + Scalar scalar( (unsigned int)value.first ); + v = Value(scalar); + } + v.SetClangType(desired_type); + StreamString idx_name; + idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); + return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData())); + } + + private: + uint64_t m_indexes; + size_t m_count; + uint32_t m_ptr_size; + Process *m_process; + + // cfr. Foundation for the details of this code + size_t _lengthForInlinePayload(uint32_t ptr_size) { + m_ptr_size = ptr_size; + if (m_ptr_size == 8) + m_count = ((m_indexes >> 3) & 0x7); + else + m_count = ((m_indexes >> 3) & 0x3); + return m_count; + } + + std::pair + _indexAtPositionForInlinePayload(size_t pos) { + if (m_ptr_size == 8) + { + switch (pos) { + case 5: return {((m_indexes >> 51) & 0x1ff),true}; + case 4: return {((m_indexes >> 42) & 0x1ff),true}; + case 3: return {((m_indexes >> 33) & 0x1ff),true}; + case 2: return {((m_indexes >> 24) & 0x1ff),true}; + case 1: return {((m_indexes >> 15) & 0x1ff),true}; + case 0: return {((m_indexes >> 6) & 0x1ff),true}; + } + } + else + { + switch (pos) { + case 2: return {((m_indexes >> 23) & 0x1ff),true}; + case 1: return {((m_indexes >> 14) & 0x1ff),true}; + case 0: return {((m_indexes >> 5) & 0x1ff),true}; + } + } + return {0,false}; + } + + }; + struct OutsourcedIndexes { + ValueObject *m_indexes; + size_t m_count; + + lldb::ValueObjectSP + GetIndexAtIndex (size_t idx) + { + if (m_indexes) + { + ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMemberFromPointer(idx, true)); + return index_sp; + } + return nullptr; + } + }; + + union { + struct InlinedIndexes m_inlined; + struct OutsourcedIndexes m_outsourced; + }; + } m_impl; + + uint32_t m_ptr_size; + ClangASTContext* m_ast_ctx; + ClangASTType m_uint_star_type; +}; + +namespace lldb_private { + namespace formatters { + + SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) + { + if (valobj_sp) + return new NSIndexPathSyntheticFrontEnd(valobj_sp); + return nullptr; + } + } +} diff --git a/source/DataFormatters/NSSet.cpp b/source/DataFormatters/NSSet.cpp index 3c7c003ed95a..194d1bd29ea1 100644 --- a/source/DataFormatters/NSSet.cpp +++ b/source/DataFormatters/NSSet.cpp @@ -25,9 +25,165 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; +namespace lldb_private { + namespace formatters { + class NSSetISyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + private: + struct DataDescriptor_32 + { + uint32_t _used : 26; + uint32_t _szidx : 6; + }; + struct DataDescriptor_64 + { + uint64_t _used : 58; + uint32_t _szidx : 6; + }; + + struct SetItemDescriptor + { + lldb::addr_t item_ptr; + lldb::ValueObjectSP valobj_sp; + }; + + public: + NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSSetISyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + lldb::addr_t m_data_ptr; + std::vector m_children; + }; + + class NSOrderedSetSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + private: + + public: + NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSOrderedSetSyntheticFrontEnd (); + private: + uint32_t m_count; + std::map m_children; + }; + + class NSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + private: + struct DataDescriptor_32 + { + uint32_t _used : 26; + uint32_t _size; + uint32_t _mutations; + uint32_t _objs_addr; + }; + struct DataDescriptor_64 + { + uint64_t _used : 58; + uint64_t _size; + uint64_t _mutations; + uint64_t _objs_addr; + }; + struct SetItemDescriptor + { + lldb::addr_t item_ptr; + lldb::ValueObjectSP valobj_sp; + }; + public: + NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSSetMSyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + std::vector m_children; + }; + + class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + NSSetCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSSetCodeRunningSyntheticFrontEnd (); + }; + } +} + template bool -lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream) +lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) @@ -313,10 +469,10 @@ lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx) process_sp->GetAddressByteSize()); set_item.valobj_sp = - ValueObject::CreateValueObjectFromData(idx_name.GetData(), - data, - m_exe_ctx_ref, - m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID)); + CreateValueObjectFromData(idx_name.GetData(), + data, + m_exe_ctx_ref, + m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID)); } return set_item.valobj_sp; } @@ -481,10 +637,10 @@ lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx) process_sp->GetAddressByteSize()); set_item.valobj_sp = - ValueObject::CreateValueObjectFromData(idx_name.GetData(), - data, - m_exe_ctx_ref, - m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID)); + CreateValueObjectFromData(idx_name.GetData(), + data, + m_exe_ctx_ref, + m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID)); } return set_item.valobj_sp; } @@ -557,7 +713,7 @@ lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::~NSOrderedSetSyntheticF } template bool -lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream); +lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); template bool -lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream); +lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); diff --git a/source/DataFormatters/StringPrinter.cpp b/source/DataFormatters/StringPrinter.cpp new file mode 100644 index 000000000000..3af5931ad716 --- /dev/null +++ b/source/DataFormatters/StringPrinter.cpp @@ -0,0 +1,650 @@ +//===-- StringPrinter.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/DataFormatters/StringPrinter.h" + +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +#include "llvm/Support/ConvertUTF.h" + +#include +#include +#include + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +// I can't use a std::unique_ptr for this because the Deleter is a template argument there +// and I want the same type to represent both pointers I want to free and pointers I don't need +// to free - which is what this class essentially is +// It's very specialized to the needs of this file, and not suggested for general use +template +struct StringPrinterBufferPointer +{ +public: + + typedef std::function Deleter; + + StringPrinterBufferPointer (std::nullptr_t ptr) : + m_data(nullptr), + m_size(0), + m_deleter() + {} + + StringPrinterBufferPointer(const T* bytes, S size, Deleter deleter = nullptr) : + m_data(bytes), + m_size(size), + m_deleter(deleter) + {} + + StringPrinterBufferPointer(const U* bytes, S size, Deleter deleter = nullptr) : + m_data((T*)bytes), + m_size(size), + m_deleter(deleter) + {} + + StringPrinterBufferPointer(StringPrinterBufferPointer&& rhs) : + m_data(rhs.m_data), + m_size(rhs.m_size), + m_deleter(rhs.m_deleter) + { + rhs.m_data = nullptr; + } + + StringPrinterBufferPointer(const StringPrinterBufferPointer& rhs) : + m_data(rhs.m_data), + m_size(rhs.m_size), + m_deleter(rhs.m_deleter) + { + rhs.m_data = nullptr; // this is why m_data has to be mutable + } + + const T* + GetBytes () const + { + return m_data; + } + + const S + GetSize () const + { + return m_size; + } + + ~StringPrinterBufferPointer () + { + if (m_data && m_deleter) + m_deleter(m_data); + m_data = nullptr; + } + + StringPrinterBufferPointer& + operator = (const StringPrinterBufferPointer& rhs) + { + if (m_data && m_deleter) + m_deleter(m_data); + m_data = rhs.m_data; + m_size = rhs.m_size; + m_deleter = rhs.m_deleter; + rhs.m_data = nullptr; + return *this; + } + +private: + mutable const T* m_data; + size_t m_size; + Deleter m_deleter; +}; + +// we define this for all values of type but only implement it for those we care about +// that's good because we get linker errors for any unsupported type +template +static StringPrinterBufferPointer<> +GetPrintableImpl(uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next); + +// mimic isprint() for Unicode codepoints +static bool +isprint(char32_t codepoint) +{ + if (codepoint <= 0x1F || codepoint == 0x7F) // C0 + { + return false; + } + if (codepoint >= 0x80 && codepoint <= 0x9F) // C1 + { + return false; + } + if (codepoint == 0x2028 || codepoint == 0x2029) // line/paragraph separators + { + return false; + } + if (codepoint == 0x200E || codepoint == 0x200F || (codepoint >= 0x202A && codepoint <= 0x202E)) // bidirectional text control + { + return false; + } + if (codepoint >= 0xFFF9 && codepoint <= 0xFFFF) // interlinears and generally specials + { + return false; + } + return true; +} + +template <> +StringPrinterBufferPointer<> +GetPrintableImpl (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) +{ + StringPrinterBufferPointer<> retval = {nullptr}; + + switch (*buffer) + { + case 0: + retval = {"\\0",2}; + break; + case '\a': + retval = {"\\a",2}; + break; + case '\b': + retval = {"\\b",2}; + break; + case '\f': + retval = {"\\f",2}; + break; + case '\n': + retval = {"\\n",2}; + break; + case '\r': + retval = {"\\r",2}; + break; + case '\t': + retval = {"\\t",2}; + break; + case '\v': + retval = {"\\v",2}; + break; + case '\"': + retval = {"\\\"",2}; + break; + case '\\': + retval = {"\\\\",2}; + break; + default: + if (isprint(*buffer)) + retval = {buffer,1}; + else + { + retval = { new uint8_t[5],4,[] (const uint8_t* c) {delete[] c;} }; + sprintf((char*)retval.GetBytes(),"\\x%02x",*buffer); + break; + } + } + + next = buffer + 1; + return retval; +} + +static char32_t +ConvertUTF8ToCodePoint (unsigned char c0, unsigned char c1) +{ + return (c0-192)*64+(c1-128); +} +static char32_t +ConvertUTF8ToCodePoint (unsigned char c0, unsigned char c1, unsigned char c2) +{ + return (c0-224)*4096+(c1-128)*64+(c2-128); +} +static char32_t +ConvertUTF8ToCodePoint (unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3) +{ + return (c0-240)*262144+(c2-128)*4096+(c2-128)*64+(c3-128); +} + +template <> +StringPrinterBufferPointer<> +GetPrintableImpl (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) +{ + StringPrinterBufferPointer<> retval {nullptr}; + + unsigned utf8_encoded_len = getNumBytesForUTF8(*buffer); + + if (1+buffer_end-buffer < utf8_encoded_len) + { + // I don't have enough bytes - print whatever I have left + retval = {buffer,static_cast(1+buffer_end-buffer)}; + next = buffer_end+1; + return retval; + } + + char32_t codepoint = 0; + switch (utf8_encoded_len) + { + case 1: + // this is just an ASCII byte - ask ASCII + return GetPrintableImpl(buffer, buffer_end, next); + case 2: + codepoint = ConvertUTF8ToCodePoint((unsigned char)*buffer, (unsigned char)*(buffer+1)); + break; + case 3: + codepoint = ConvertUTF8ToCodePoint((unsigned char)*buffer, (unsigned char)*(buffer+1), (unsigned char)*(buffer+2)); + break; + case 4: + codepoint = ConvertUTF8ToCodePoint((unsigned char)*buffer, (unsigned char)*(buffer+1), (unsigned char)*(buffer+2), (unsigned char)*(buffer+3)); + break; + default: + // this is probably some bogus non-character thing + // just print it as-is and hope to sync up again soon + retval = {buffer,1}; + next = buffer+1; + return retval; + } + + if (codepoint) + { + switch (codepoint) + { + case 0: + retval = {"\\0",2}; + break; + case '\a': + retval = {"\\a",2}; + break; + case '\b': + retval = {"\\b",2}; + break; + case '\f': + retval = {"\\f",2}; + break; + case '\n': + retval = {"\\n",2}; + break; + case '\r': + retval = {"\\r",2}; + break; + case '\t': + retval = {"\\t",2}; + break; + case '\v': + retval = {"\\v",2}; + break; + case '\"': + retval = {"\\\"",2}; + break; + case '\\': + retval = {"\\\\",2}; + break; + default: + if (isprint(codepoint)) + retval = {buffer,utf8_encoded_len}; + else + { + retval = { new uint8_t[11],10,[] (const uint8_t* c) {delete[] c;} }; + sprintf((char*)retval.GetBytes(),"\\U%08x",codepoint); + break; + } + } + + next = buffer + utf8_encoded_len; + return retval; + } + + // this should not happen - but just in case.. try to resync at some point + retval = {buffer,1}; + next = buffer+1; + return retval; +} + +// Given a sequence of bytes, this function returns: +// a sequence of bytes to actually print out + a length +// the following unscanned position of the buffer is in next +static StringPrinterBufferPointer<> +GetPrintable(StringElementType type, uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) +{ + if (!buffer) + return {nullptr}; + + switch (type) + { + case StringElementType::ASCII: + return GetPrintableImpl(buffer, buffer_end, next); + case StringElementType::UTF8: + return GetPrintableImpl(buffer, buffer_end, next); + default: + return {nullptr}; + } +} + +// use this call if you already have an LLDB-side buffer for the data +template +static bool +DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**, + const SourceDataType*, + UTF8**, + UTF8*, + ConversionFlags), + const DataExtractor& data, + Stream& stream, + char prefix_token, + char quote, + uint32_t sourceSize, + bool escapeNonPrintables) +{ + if (prefix_token != 0) + stream.Printf("%c",prefix_token); + if (quote != 0) + stream.Printf("%c",quote); + if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd()) + { + const int bufferSPSize = data.GetByteSize(); + if (sourceSize == 0) + { + const int origin_encoding = 8*sizeof(SourceDataType); + sourceSize = bufferSPSize/(origin_encoding / 4); + } + + SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart(); + SourceDataType *data_end_ptr = data_ptr + sourceSize; + + while (data_ptr < data_end_ptr) + { + if (!*data_ptr) + { + data_end_ptr = data_ptr; + break; + } + data_ptr++; + } + + data_ptr = (SourceDataType*)data.GetDataStart(); + + lldb::DataBufferSP utf8_data_buffer_sp; + UTF8* utf8_data_ptr = nullptr; + UTF8* utf8_data_end_ptr = nullptr; + + if (ConvertFunction) + { + utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0)); + utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); + utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize(); + ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion ); + utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr + } + else + { + // just copy the pointers - the cast is necessary to make the compiler happy + // but this should only happen if we are reading UTF8 data + utf8_data_ptr = (UTF8*)data_ptr; + utf8_data_end_ptr = (UTF8*)data_end_ptr; + } + + // since we tend to accept partial data (and even partially malformed data) + // we might end up with no NULL terminator before the end_ptr + // hence we need to take a slower route and ensure we stay within boundaries + for (;utf8_data_ptr < utf8_data_end_ptr;) + { + if (!*utf8_data_ptr) + break; + + if (escapeNonPrintables) + { + uint8_t* next_data = nullptr; + auto printable = GetPrintable(StringElementType::UTF8, utf8_data_ptr, utf8_data_end_ptr, next_data); + auto printable_bytes = printable.GetBytes(); + auto printable_size = printable.GetSize(); + if (!printable_bytes || !next_data) + { + // GetPrintable() failed on us - print one byte in a desperate resync attempt + printable_bytes = utf8_data_ptr; + printable_size = 1; + next_data = utf8_data_ptr+1; + } + for (unsigned c = 0; c < printable_size; c++) + stream.Printf("%c", *(printable_bytes+c)); + utf8_data_ptr = (uint8_t*)next_data; + } + else + { + stream.Printf("%c",*utf8_data_ptr); + utf8_data_ptr++; + } + } + } + if (quote != 0) + stream.Printf("%c",quote); + return true; +} + +lldb_private::formatters::ReadStringAndDumpToStreamOptions::ReadStringAndDumpToStreamOptions (ValueObject& valobj) : + ReadStringAndDumpToStreamOptions() +{ + SetEscapeNonPrintables(valobj.GetTargetSP()->GetDebugger().GetEscapeNonPrintables()); +} + +lldb_private::formatters::ReadBufferAndDumpToStreamOptions::ReadBufferAndDumpToStreamOptions (ValueObject& valobj) : + ReadBufferAndDumpToStreamOptions() +{ + SetEscapeNonPrintables(valobj.GetTargetSP()->GetDebugger().GetEscapeNonPrintables()); +} + + +namespace lldb_private +{ + +namespace formatters +{ + +template <> +bool +ReadStringAndDumpToStream (ReadStringAndDumpToStreamOptions options) +{ + assert(options.GetStream() && "need a Stream to print the string to"); + Error my_error; + size_t my_data_read; + + ProcessSP process_sp(options.GetProcessSP()); + + if (process_sp.get() == nullptr || options.GetLocation() == 0) + return false; + + size_t size; + + if (options.GetSourceSize() == 0) + size = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); + else if (!options.GetIgnoreMaxLength()) + size = std::min(options.GetSourceSize(),process_sp->GetTarget().GetMaximumSizeOfStringSummary()); + else + size = options.GetSourceSize(); + + lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0)); + + my_data_read = process_sp->ReadCStringFromMemory(options.GetLocation(), (char*)buffer_sp->GetBytes(), size, my_error); + + if (my_error.Fail()) + return false; + + char prefix_token = options.GetPrefixToken(); + char quote = options.GetQuote(); + + if (prefix_token != 0) + options.GetStream()->Printf("%c%c",prefix_token,quote); + else if (quote != 0) + options.GetStream()->Printf("%c",quote); + + uint8_t* data_end = buffer_sp->GetBytes()+buffer_sp->GetByteSize(); + + // since we tend to accept partial data (and even partially malformed data) + // we might end up with no NULL terminator before the end_ptr + // hence we need to take a slower route and ensure we stay within boundaries + for (uint8_t* data = buffer_sp->GetBytes(); *data && (data < data_end);) + { + if (options.GetEscapeNonPrintables()) + { + uint8_t* next_data = nullptr; + auto printable = GetPrintable(StringElementType::ASCII, data, data_end, next_data); + auto printable_bytes = printable.GetBytes(); + auto printable_size = printable.GetSize(); + if (!printable_bytes || !next_data) + { + // GetPrintable() failed on us - print one byte in a desperate resync attempt + printable_bytes = data; + printable_size = 1; + next_data = data+1; + } + for (unsigned c = 0; c < printable_size; c++) + options.GetStream()->Printf("%c", *(printable_bytes+c)); + data = (uint8_t*)next_data; + } + else + { + options.GetStream()->Printf("%c",*data); + data++; + } + } + + if (quote != 0) + options.GetStream()->Printf("%c",quote); + + return true; +} + +template +static bool +ReadUTFBufferAndDumpToStream (const ReadStringAndDumpToStreamOptions& options, + ConversionResult (*ConvertFunction) (const SourceDataType**, + const SourceDataType*, + UTF8**, + UTF8*, + ConversionFlags)) +{ + assert(options.GetStream() && "need a Stream to print the string to"); + + if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS) + return false; + + lldb::ProcessSP process_sp(options.GetProcessSP()); + + if (!process_sp) + return false; + + const int type_width = sizeof(SourceDataType); + const int origin_encoding = 8 * type_width ; + if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32) + return false; + // if not UTF8, I need a conversion function to return proper UTF8 + if (origin_encoding != 8 && !ConvertFunction) + return false; + + if (!options.GetStream()) + return false; + + uint32_t sourceSize = options.GetSourceSize(); + bool needs_zero_terminator = options.GetNeedsZeroTermination(); + + if (!sourceSize) + { + sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); + needs_zero_terminator = true; + } + else + sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary()); + + const int bufferSPSize = sourceSize * type_width; + + lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0)); + + if (!buffer_sp->GetBytes()) + return false; + + Error error; + char *buffer = reinterpret_cast(buffer_sp->GetBytes()); + + size_t data_read = 0; + if (needs_zero_terminator) + data_read = process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width); + else + data_read = process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error); + + if (error.Fail()) + { + options.GetStream()->Printf("unable to read data"); + return true; + } + + DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); + + return DumpUTFBufferToStream(ConvertFunction, data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize, options.GetEscapeNonPrintables()); +} + +template <> +bool +ReadStringAndDumpToStream (ReadStringAndDumpToStreamOptions options) +{ + return ReadUTFBufferAndDumpToStream(options, + nullptr); +} + +template <> +bool +ReadStringAndDumpToStream (ReadStringAndDumpToStreamOptions options) +{ + return ReadUTFBufferAndDumpToStream(options, + ConvertUTF16toUTF8); +} + +template <> +bool +ReadStringAndDumpToStream (ReadStringAndDumpToStreamOptions options) +{ + return ReadUTFBufferAndDumpToStream(options, + ConvertUTF32toUTF8); +} + +template <> +bool +ReadBufferAndDumpToStream (ReadBufferAndDumpToStreamOptions options) +{ + assert(options.GetStream() && "need a Stream to print the string to"); + + return DumpUTFBufferToStream(nullptr, options.GetData(), *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), options.GetSourceSize(), options.GetEscapeNonPrintables()); +} + +template <> +bool +ReadBufferAndDumpToStream (ReadBufferAndDumpToStreamOptions options) +{ + // treat ASCII the same as UTF8 + // FIXME: can we optimize ASCII some more? + return ReadBufferAndDumpToStream(options); +} + +template <> +bool +ReadBufferAndDumpToStream (ReadBufferAndDumpToStreamOptions options) +{ + assert(options.GetStream() && "need a Stream to print the string to"); + + return DumpUTFBufferToStream(ConvertUTF16toUTF8, options.GetData(), *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), options.GetSourceSize(), options.GetEscapeNonPrintables()); +} + +template <> +bool +ReadBufferAndDumpToStream (ReadBufferAndDumpToStreamOptions options) +{ + assert(options.GetStream() && "need a Stream to print the string to"); + + return DumpUTFBufferToStream(ConvertUTF32toUTF8, options.GetData(), *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), options.GetSourceSize(), options.GetEscapeNonPrintables()); +} + +} // namespace formatters + +} // namespace lldb_private diff --git a/source/DataFormatters/TypeCategory.cpp b/source/DataFormatters/TypeCategory.cpp index 322d1cf55437..3df6884fe679 100644 --- a/source/DataFormatters/TypeCategory.cpp +++ b/source/DataFormatters/TypeCategory.cpp @@ -27,6 +27,7 @@ m_filter_cont("filter","regex-filter",clist), #ifndef LLDB_DISABLE_PYTHON m_synth_cont("synth","regex-synth",clist), #endif +m_validator_cont("validator","regex-validator",clist), m_enabled(false), m_change_listener(clist), m_mutex(Mutex::eMutexTypeRecursive), @@ -129,6 +130,22 @@ TypeCategoryImpl::Get (ValueObject& valobj, return false; } +bool +TypeCategoryImpl::Get (ValueObject& valobj, + const FormattersMatchVector& candidates, + lldb::TypeValidatorImplSP& entry, + uint32_t* reason) +{ + if (!IsEnabled()) + return false; + if (GetTypeValidatorsContainer()->Get(candidates, entry, reason)) + return true; + bool regex = GetRegexTypeValidatorsContainer()->Get(candidates, entry, reason); + if (regex && reason) + *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary; + return regex; +} + void TypeCategoryImpl::Clear (FormatCategoryItems items) { @@ -153,6 +170,11 @@ TypeCategoryImpl::Clear (FormatCategoryItems items) if ( (items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth ) GetRegexTypeSyntheticsContainer()->Clear(); #endif + + if ( (items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator ) + GetTypeValidatorsContainer()->Clear(); + if ( (items & eFormatCategoryItemRegexValidator) == eFormatCategoryItemRegexValidator ) + GetRegexTypeValidatorsContainer()->Clear(); } bool @@ -182,6 +204,12 @@ TypeCategoryImpl::Delete (ConstString name, if ( (items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth ) success = GetRegexTypeSyntheticsContainer()->Delete(name) || success; #endif + + if ( (items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator ) + success = GetTypeValidatorsContainer()->Delete(name) || success; + if ( (items & eFormatCategoryItemRegexValidator) == eFormatCategoryItemRegexValidator ) + success = GetRegexTypeValidatorsContainer()->Delete(name) || success; + return success; } @@ -211,6 +239,12 @@ TypeCategoryImpl::GetCount (FormatCategoryItems items) if ( (items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth ) count += GetRegexTypeSyntheticsContainer()->GetCount(); #endif + + if ( (items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator ) + count += GetTypeValidatorsContainer()->GetCount(); + if ( (items & eFormatCategoryItemRegexValidator) == eFormatCategoryItemRegexValidator ) + count += GetRegexTypeValidatorsContainer()->GetCount(); + return count; } @@ -230,6 +264,7 @@ TypeCategoryImpl::AnyMatches(ConstString type_name, #ifndef LLDB_DISABLE_PYTHON ScriptedSyntheticChildren::SharedPointer synth_sp; #endif + TypeValidatorImpl::SharedPointer validator_sp; if ( (items & eFormatCategoryItemValue) == eFormatCategoryItemValue ) { @@ -324,6 +359,30 @@ TypeCategoryImpl::AnyMatches(ConstString type_name, } } #endif + + if ( (items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator ) + { + if (GetTypeValidatorsContainer()->Get(type_name, validator_sp)) + { + if (matching_category) + *matching_category = m_name.GetCString(); + if (matching_type) + *matching_type = eFormatCategoryItemValidator; + return true; + } + } + if ( (items & eFormatCategoryItemRegexValidator) == eFormatCategoryItemRegexValidator ) + { + if (GetRegexTypeValidatorsContainer()->Get(type_name, validator_sp)) + { + if (matching_category) + *matching_category = m_name.GetCString(); + if (matching_type) + *matching_type = eFormatCategoryItemRegexValidator; + return true; + } + } + return false; } @@ -393,6 +452,22 @@ TypeCategoryImpl::GetSyntheticForType (lldb::TypeNameSpecifierImplSP type_sp) } #endif +TypeCategoryImpl::ValidatorContainer::MapValueType +TypeCategoryImpl::GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp) +{ + ValidatorContainer::MapValueType retval; + + if (type_sp) + { + if (type_sp->IsRegex()) + GetRegexTypeValidatorsContainer()->GetExact(ConstString(type_sp->GetName()),retval); + else + GetTypeValidatorsContainer()->GetExact(ConstString(type_sp->GetName()),retval); + } + + return retval; +} + lldb::TypeNameSpecifierImplSP TypeCategoryImpl::GetTypeNameSpecifierForSummaryAtIndex (size_t index) { @@ -467,12 +542,30 @@ TypeCategoryImpl::GetTypeNameSpecifierForSyntheticAtIndex (size_t index) } #endif +TypeCategoryImpl::ValidatorContainer::MapValueType +TypeCategoryImpl::GetValidatorAtIndex (size_t index) +{ + if (index < GetTypeValidatorsContainer()->GetCount()) + return GetTypeValidatorsContainer()->GetAtIndex(index); + else + return GetRegexTypeValidatorsContainer()->GetAtIndex(index-GetTypeValidatorsContainer()->GetCount()); +} + +lldb::TypeNameSpecifierImplSP +TypeCategoryImpl::GetTypeNameSpecifierForValidatorAtIndex (size_t index) +{ + if (index < GetTypeValidatorsContainer()->GetCount()) + return GetTypeValidatorsContainer()->GetTypeNameSpecifierAtIndex(index); + else + return GetRegexTypeValidatorsContainer()->GetTypeNameSpecifierAtIndex(index - GetTypeValidatorsContainer()->GetCount()); +} + void TypeCategoryImpl::Enable (bool value, uint32_t position) { Mutex::Locker locker(m_mutex); - m_enabled = value; - m_enabled_position = position; + if ( (m_enabled = value) ) + m_enabled_position = position; if (m_change_listener) m_change_listener->Changed(); } diff --git a/source/DataFormatters/TypeCategoryMap.cpp b/source/DataFormatters/TypeCategoryMap.cpp index c6dba1b9f4bd..ae34d0339011 100644 --- a/source/DataFormatters/TypeCategoryMap.cpp +++ b/source/DataFormatters/TypeCategoryMap.cpp @@ -119,6 +119,46 @@ TypeCategoryMap::Disable (ValueSP category) return false; } +void +TypeCategoryMap::EnableAllCategories () +{ + Mutex::Locker locker(m_map_mutex); + std::vector sorted_categories(m_map.size(), ValueSP()); + MapType::iterator iter = m_map.begin(), end = m_map.end(); + for (; iter != end; ++iter) + { + if (iter->second->IsEnabled()) + continue; + auto pos = iter->second->GetLastEnabledPosition(); + if (pos >= sorted_categories.size()) + { + auto iter = std::find_if(sorted_categories.begin(), + sorted_categories.end(), + [] (const ValueSP& sp) -> bool { + return sp.get() == nullptr; + }); + pos = std::distance(sorted_categories.begin(), iter); + } + sorted_categories.at(pos) = iter->second; + } + decltype(sorted_categories)::iterator viter = sorted_categories.begin(), vend = sorted_categories.end(); + for (; viter != vend; viter++) + if (viter->get()) + Enable(*viter, Last); +} + +void +TypeCategoryMap::DisableAllCategories () +{ + Mutex::Locker locker(m_map_mutex); + Position p = First; + for (; false == m_active_categories.empty(); p++) + { + m_active_categories.front()->SetEnabledPosition(p); + Disable(m_active_categories.front()); + } +} + void TypeCategoryMap::Clear () { @@ -266,6 +306,34 @@ TypeCategoryMap::GetSyntheticChildren (ValueObject& valobj, } #endif +lldb::TypeValidatorImplSP +TypeCategoryMap::GetValidator (ValueObject& valobj, + lldb::DynamicValueType use_dynamic) +{ + Mutex::Locker locker(m_map_mutex); + + uint32_t reason_why; + ActiveCategoriesIterator begin, end = m_active_categories.end(); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); + + FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic); + + for (begin = m_active_categories.begin(); begin != end; begin++) + { + lldb::TypeCategoryImplSP category_sp = *begin; + lldb::TypeValidatorImplSP current_format; + if (log) + log->Printf("\n[CategoryMap::GetValidator] Trying to use category %s", category_sp->GetName()); + if (!category_sp->Get(valobj, matches, current_format, &reason_why)) + continue; + return current_format; + } + if (log) + log->Printf("[CategoryMap::GetValidator] nothing found - returning empty SP"); + return lldb::TypeValidatorImplSP(); +} + void TypeCategoryMap::LoopThrough(CallbackType callback, void* param) { diff --git a/source/DataFormatters/TypeFormat.cpp b/source/DataFormatters/TypeFormat.cpp index 0c62daf87bbc..f07d8127d2b9 100644 --- a/source/DataFormatters/TypeFormat.cpp +++ b/source/DataFormatters/TypeFormat.cpp @@ -59,9 +59,9 @@ TypeFormatImpl_Format::FormatObject (ValueObject *valobj, { if (!valobj) return false; - if (valobj->GetClangType().IsAggregateType () == false) + if (valobj->CanProvideValue()) { - const Value& value(valobj->GetValue()); + Value& value(valobj->GetValue()); const Value::ContextType context_type = value.GetContextType(); ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); DataExtractor data; @@ -92,14 +92,14 @@ TypeFormatImpl_Format::FormatObject (ValueObject *valobj, } else { - ClangASTType clang_type = valobj->GetClangType (); + ClangASTType clang_type = value.GetClangType (); if (clang_type) { // put custom bytes to display in the DataExtractor to override the default value logic if (GetFormat() == eFormatCString) { lldb_private::Flags type_flags(clang_type.GetTypeInfo(NULL)); // disambiguate w.r.t. TypeFormatImpl::Flags - if (type_flags.Test(ClangASTType::eTypeIsPointer) && !type_flags.Test(ClangASTType::eTypeIsObjC)) + if (type_flags.Test(eTypeIsPointer) && !type_flags.Test(eTypeIsObjC)) { // if we are dumping a pointer as a c-string, get the pointee data as a string TargetSP target_sp(valobj->GetTargetSP()); @@ -180,7 +180,7 @@ TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj, dest.clear(); if (!valobj) return false; - if (valobj->GetClangType().IsAggregateType ()) + if (!valobj->CanProvideValue()) return false; ProcessSP process_sp; TargetSP target_sp; @@ -209,7 +209,7 @@ TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj, { if (!type_sp) continue; - if ( (type_sp->GetClangForwardType().GetTypeInfo() & ClangASTType::eTypeIsEnumeration) == ClangASTType::eTypeIsEnumeration) + if ( (type_sp->GetClangForwardType().GetTypeInfo() & eTypeIsEnumeration) == eTypeIsEnumeration) { valobj_enum_type = type_sp->GetClangFullType(); m_types.emplace(valobj_key,valobj_enum_type); diff --git a/source/DataFormatters/TypeSummary.cpp b/source/DataFormatters/TypeSummary.cpp index e5d80174c3cc..ff089af58cb7 100644 --- a/source/DataFormatters/TypeSummary.cpp +++ b/source/DataFormatters/TypeSummary.cpp @@ -34,6 +34,50 @@ using namespace lldb; using namespace lldb_private; +TypeSummaryOptions::TypeSummaryOptions () : + m_lang(eLanguageTypeUnknown), + m_capping(eTypeSummaryCapped) +{} + +TypeSummaryOptions::TypeSummaryOptions (const TypeSummaryOptions& rhs) : + m_lang(rhs.m_lang), + m_capping(rhs.m_capping) +{} + +TypeSummaryOptions& +TypeSummaryOptions::operator = (const TypeSummaryOptions& rhs) +{ + m_lang = rhs.m_lang; + m_capping = rhs.m_capping; + return *this; +} + +lldb::LanguageType +TypeSummaryOptions::GetLanguage () const +{ + return m_lang; +} + +lldb::TypeSummaryCapping +TypeSummaryOptions::GetCapping () const +{ + return m_capping; +} + +TypeSummaryOptions& +TypeSummaryOptions::SetLanguage (lldb::LanguageType lang) +{ + m_lang = lang; + return *this; +} + +TypeSummaryOptions& +TypeSummaryOptions::SetCapping (lldb::TypeSummaryCapping cap) +{ + m_capping = cap; + return *this; +} + TypeSummaryImpl::TypeSummaryImpl (const TypeSummaryImpl::Flags& flags) : m_flags(flags) { @@ -51,7 +95,8 @@ m_format() bool StringSummaryFormat::FormatObject (ValueObject *valobj, - std::string& retval) + std::string& retval, + const TypeSummaryOptions& options) { if (!valobj) { @@ -115,11 +160,12 @@ m_description(description ? description : "") bool CXXFunctionSummaryFormat::FormatObject (ValueObject *valobj, - std::string& dest) + std::string& dest, + const TypeSummaryOptions& options) { dest.clear(); StreamString stream; - if (!m_impl || m_impl(*valobj,stream) == false) + if (!m_impl || m_impl(*valobj,stream,options) == false) return false; dest.assign(stream.GetData()); return true; @@ -160,7 +206,8 @@ m_script_function_sp() bool ScriptSummaryFormat::FormatObject (ValueObject *valobj, - std::string& retval) + std::string& retval, + const TypeSummaryOptions& options) { Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); @@ -190,6 +237,7 @@ ScriptSummaryFormat::FormatObject (ValueObject *valobj, return script_interpreter->GetScriptedSummary(m_function_name.c_str(), valobj->GetSP(), m_script_function_sp, + options, retval); } diff --git a/source/DataFormatters/TypeSynthetic.cpp b/source/DataFormatters/TypeSynthetic.cpp index 3949673a4be8..13c1c7508b68 100644 --- a/source/DataFormatters/TypeSynthetic.cpp +++ b/source/DataFormatters/TypeSynthetic.cpp @@ -23,6 +23,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/DataFormatters/TypeSynthetic.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/ScriptInterpreterPython.h" #include "lldb/Symbol/ClangASTType.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" @@ -30,6 +31,59 @@ using namespace lldb; using namespace lldb_private; +void +TypeFilterImpl::AddExpressionPath (const std::string& path) +{ + bool need_add_dot = true; + if (path[0] == '.' || + (path[0] == '-' && path[1] == '>') || + path[0] == '[') + need_add_dot = false; + // add a '.' symbol to help forgetful users + if(!need_add_dot) + m_expression_paths.push_back(path); + else + m_expression_paths.push_back(std::string(".") + path); +} + +bool +TypeFilterImpl::SetExpressionPathAtIndex (size_t i, const std::string& path) +{ + if (i >= GetCount()) + return false; + bool need_add_dot = true; + if (path[0] == '.' || + (path[0] == '-' && path[1] == '>') || + path[0] == '[') + need_add_dot = false; + // add a '.' symbol to help forgetful users + if(!need_add_dot) + m_expression_paths[i] = path; + else + m_expression_paths[i] = std::string(".") + path; + return true; +} + +size_t +TypeFilterImpl::FrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ + const char* name_cstr = name.GetCString(); + for (size_t i = 0; i < filter->GetCount(); i++) + { + const char* expr_cstr = filter->GetExpressionPathAtIndex(i); + if (expr_cstr) + { + if (*expr_cstr == '.') + expr_cstr++; + else if (*expr_cstr == '-' && *(expr_cstr+1) == '>') + expr_cstr += 2; + } + if (!::strcmp(name_cstr, expr_cstr)) + return i; + } + return UINT32_MAX; +} + std::string TypeFilterImpl::GetDescription() { @@ -63,6 +117,41 @@ CXXSyntheticChildren::GetDescription() return sstr.GetString(); } +lldb::ValueObjectSP +SyntheticChildrenFrontEnd::CreateValueObjectFromExpression (const char* name, + const char* expression, + const ExecutionContext& exe_ctx) +{ + ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromExpression(name, expression, exe_ctx)); + if (valobj_sp) + valobj_sp->SetSyntheticChildrenGenerated(true); + return valobj_sp; +} + +lldb::ValueObjectSP +SyntheticChildrenFrontEnd::CreateValueObjectFromAddress (const char* name, + uint64_t address, + const ExecutionContext& exe_ctx, + ClangASTType type) +{ + ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromAddress(name, address, exe_ctx, type)); + if (valobj_sp) + valobj_sp->SetSyntheticChildrenGenerated(true); + return valobj_sp; +} + +lldb::ValueObjectSP +SyntheticChildrenFrontEnd::CreateValueObjectFromData (const char* name, + const DataExtractor& data, + const ExecutionContext& exe_ctx, + ClangASTType type) +{ + ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromData(name, data, exe_ctx, type)); + if (valobj_sp) + valobj_sp->SetSyntheticChildrenGenerated(true); + return valobj_sp; +} + #ifndef LLDB_DISABLE_PYTHON ScriptedSyntheticChildren::FrontEnd::FrontEnd(std::string pclass, ValueObject &backend) : @@ -98,6 +187,55 @@ ScriptedSyntheticChildren::FrontEnd::GetChildAtIndex (size_t idx) return m_interpreter->GetChildAtIndex(m_wrapper_sp, idx); } +bool +ScriptedSyntheticChildren::FrontEnd::IsValid () +{ + return m_wrapper_sp.get() != nullptr && m_wrapper_sp->operator bool() && m_interpreter != nullptr; +} + +size_t +ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren () +{ + if (!m_wrapper_sp || m_interpreter == NULL) + return 0; + return m_interpreter->CalculateNumChildren(m_wrapper_sp); +} + +bool +ScriptedSyntheticChildren::FrontEnd::Update () +{ + if (!m_wrapper_sp || m_interpreter == NULL) + return false; + + return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp); +} + +bool +ScriptedSyntheticChildren::FrontEnd::MightHaveChildren () +{ + if (!m_wrapper_sp || m_interpreter == NULL) + return false; + + return m_interpreter->MightHaveChildrenSynthProviderInstance(m_wrapper_sp); +} + +size_t +ScriptedSyntheticChildren::FrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ + if (!m_wrapper_sp || m_interpreter == NULL) + return UINT32_MAX; + return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp, name.GetCString()); +} + +lldb::ValueObjectSP +ScriptedSyntheticChildren::FrontEnd::GetSyntheticValue () +{ + if (!m_wrapper_sp || m_interpreter == NULL) + return nullptr; + + return m_interpreter->GetSyntheticValue(m_wrapper_sp); +} + std::string ScriptedSyntheticChildren::GetDescription() { diff --git a/source/DataFormatters/TypeValidator.cpp b/source/DataFormatters/TypeValidator.cpp new file mode 100644 index 000000000000..b5efac8f586a --- /dev/null +++ b/source/DataFormatters/TypeValidator.cpp @@ -0,0 +1,75 @@ +//===-- TypeValidator.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes + +// C++ Includes + +// Other libraries and framework includes + +// Project includes +#include "lldb/DataFormatters/TypeValidator.h" +#include "lldb/Core/StreamString.h" + +using namespace lldb; +using namespace lldb_private; + +TypeValidatorImpl::TypeValidatorImpl(const Flags &flags) : + m_flags(flags), + m_my_revision(0) +{ +} + +TypeValidatorImpl::~TypeValidatorImpl() +{ +} + +TypeValidatorImpl::ValidationResult +TypeValidatorImpl::Success () +{ + return ValidationResult { TypeValidatorResult::Success, "" }; +} + +TypeValidatorImpl::ValidationResult +TypeValidatorImpl::Failure (std::string message) +{ + return ValidationResult { TypeValidatorResult::Failure, message }; +} + +TypeValidatorImpl_CXX::TypeValidatorImpl_CXX (ValidatorFunction f, std::string d, const TypeValidatorImpl::Flags& flags) : + TypeValidatorImpl(flags), + m_description(d), + m_validator_function(f) +{ +} + +TypeValidatorImpl_CXX::~TypeValidatorImpl_CXX() +{ +} + +TypeValidatorImpl::ValidationResult +TypeValidatorImpl_CXX::FormatObject (ValueObject *valobj) const +{ + if (!valobj) + return Success(); // I guess there's nothing wrong with a null valueobject.. + + return m_validator_function(valobj); +} + +std::string +TypeValidatorImpl_CXX::GetDescription() +{ + StreamString sstr; + sstr.Printf ("%s%s%s%s", + m_description.c_str(), + Cascades() ? "" : " (not cascading)", + SkipsPointers() ? " (skip pointers)" : "", + SkipsReferences() ? " (skip references)" : ""); + return sstr.GetString(); +} diff --git a/source/DataFormatters/ValueObjectPrinter.cpp b/source/DataFormatters/ValueObjectPrinter.cpp index 65e5e3f45823..5560ce2971e7 100644 --- a/source/DataFormatters/ValueObjectPrinter.cpp +++ b/source/DataFormatters/ValueObjectPrinter.cpp @@ -66,11 +66,13 @@ ValueObjectPrinter::Init (ValueObject* valobj, bool ValueObjectPrinter::PrintValueObject () { - if (!GetDynamicValueIfNeeded () || m_valobj == nullptr) + if (!GetMostSpecializedValue () || m_valobj == nullptr) return false; if (ShouldPrintValueObject()) { + PrintValidationMarkerIfNeeded(); + PrintLocationIfNeeded(); m_stream->Indent(); @@ -89,11 +91,13 @@ ValueObjectPrinter::PrintValueObject () else m_stream->EOL(); + PrintValidationErrorIfNeeded(); + return true; } bool -ValueObjectPrinter::GetDynamicValueIfNeeded () +ValueObjectPrinter::GetMostSpecializedValue () { if (m_valobj) return true; @@ -130,6 +134,25 @@ ValueObjectPrinter::GetDynamicValueIfNeeded () else m_valobj = m_orig_valobj; } + + if (m_valobj->IsSynthetic()) + { + if (options.m_use_synthetic == false) + { + ValueObject *non_synthetic = m_valobj->GetNonSyntheticValue().get(); + if (non_synthetic) + m_valobj = non_synthetic; + } + } + else + { + if (options.m_use_synthetic == true) + { + ValueObject *synthetic = m_valobj->GetSyntheticValue().get(); + if (synthetic) + m_valobj = synthetic; + } + } } m_clang_type = m_valobj->GetClangType(); m_type_flags = m_clang_type.GetTypeInfo (); @@ -160,7 +183,7 @@ bool ValueObjectPrinter::ShouldPrintValueObject () { if (m_should_print == eLazyBoolCalculate) - m_should_print = (options.m_flat_output == false || m_type_flags.Test (ClangASTType::eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo; + m_should_print = (options.m_flat_output == false || m_type_flags.Test (eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo; return m_should_print == eLazyBoolYes; } @@ -176,7 +199,7 @@ bool ValueObjectPrinter::IsPtr () { if (m_is_ptr == eLazyBoolCalculate) - m_is_ptr = m_type_flags.Test (ClangASTType::eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo; + m_is_ptr = m_type_flags.Test (eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo; return m_is_ptr == eLazyBoolYes; } @@ -184,7 +207,7 @@ bool ValueObjectPrinter::IsRef () { if (m_is_ref == eLazyBoolCalculate) - m_is_ref = m_type_flags.Test (ClangASTType::eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo; + m_is_ref = m_type_flags.Test (eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo; return m_is_ref == eLazyBoolYes; } @@ -192,7 +215,7 @@ bool ValueObjectPrinter::IsAggregate () { if (m_is_aggregate == eLazyBoolCalculate) - m_is_aggregate = m_type_flags.Test (ClangASTType::eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo; + m_is_aggregate = m_type_flags.Test (eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo; return m_is_aggregate == eLazyBoolYes; } @@ -222,13 +245,13 @@ ValueObjectPrinter::PrintTypeIfNeeded () { // Some ValueObjects don't have types (like registers sets). Only print // the type if there is one to print - ConstString qualified_type_name; - if (options.m_be_raw) - qualified_type_name = m_valobj->GetQualifiedTypeName(); + ConstString type_name; + if (options.m_use_type_display_name) + type_name = m_valobj->GetDisplayTypeName(); else - qualified_type_name = m_valobj->GetDisplayTypeName(); - if (qualified_type_name) - m_stream->Printf("(%s) ", qualified_type_name.GetCString()); + type_name = m_valobj->GetQualifiedTypeName(); + if (type_name) + m_stream->Printf("(%s) ", type_name.GetCString()); else show_type = false; } @@ -438,8 +461,7 @@ ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description, ValueObject* ValueObjectPrinter::GetValueObjectForChildrenGeneration () { - ValueObjectSP synth_valobj_sp = m_valobj->GetSyntheticValue (options.m_use_synthetic); - return (synth_valobj_sp ? synth_valobj_sp.get() : m_valobj); + return m_valobj; } void @@ -536,7 +558,13 @@ ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth) { // Aggregate, no children... if (ShouldPrintValueObject()) - m_stream->PutCString(" {}\n"); + { + // if it has a synthetic value, then don't print {}, the synthetic children are probably only being used to vend a value + if (m_valobj->DoesProvideSyntheticValue()) + m_stream->PutCString( "\n"); + else + m_stream->PutCString(" {}\n"); + } } else { @@ -548,7 +576,7 @@ ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth) bool ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names) { - if (!GetDynamicValueIfNeeded () || m_valobj == nullptr) + if (!GetMostSpecializedValue () || m_valobj == nullptr) return false; ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); @@ -563,9 +591,8 @@ ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names) for (uint32_t idx=0; idxGetChildAtIndex(idx, true)); - lldb::ValueObjectSP child_dyn_sp = child_sp.get() ? child_sp->GetDynamicValue(options.m_use_dynamic) : child_sp; - if (child_dyn_sp) - child_sp = child_dyn_sp; + if (child_sp) + child_sp = child_sp->GetQualifiedRepresentationIfAvailable(options.m_use_dynamic, options.m_use_synthetic); if (child_sp) { if (idx) @@ -604,7 +631,7 @@ ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed, uint32_t curr_ptr_depth = m_ptr_depth; bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth); - bool print_oneline = (curr_ptr_depth > 0 || options.m_show_types || options.m_be_raw) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj); + bool print_oneline = (curr_ptr_depth > 0 || options.m_show_types || !options.m_allow_oneliner_mode) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj); if (print_children) { @@ -624,3 +651,44 @@ ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed, else m_stream->EOL(); } + +bool +ValueObjectPrinter::ShouldPrintValidation () +{ + return options.m_run_validator; +} + +bool +ValueObjectPrinter::PrintValidationMarkerIfNeeded () +{ + if (!ShouldPrintValidation()) + return false; + + m_validation = m_valobj->GetValidationStatus(); + + if (TypeValidatorResult::Failure == m_validation.first) + { + m_stream->Printf("! "); + return true; + } + + return false; +} + +bool +ValueObjectPrinter::PrintValidationErrorIfNeeded () +{ + if (!ShouldPrintValidation()) + return false; + + if (TypeValidatorResult::Success == m_validation.first) + return false; + + if (m_validation.second.empty()) + m_validation.second.assign("unknown error"); + + m_stream->Printf(" ! validation error: %s", m_validation.second.c_str()); + m_stream->EOL(); + + return true; +} diff --git a/source/Expression/ClangASTSource.cpp b/source/Expression/ClangASTSource.cpp index d488993b90d7..9a6d6e532255 100644 --- a/source/Expression/ClangASTSource.cpp +++ b/source/Expression/ClangASTSource.cpp @@ -708,6 +708,8 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, else m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, types); + bool found_a_type = false; + if (types.GetSize()) { lldb::TypeSP type_sp = types.GetTypeAtIndex(0); @@ -736,8 +738,62 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, } context.AddTypeDecl(copied_clang_type); + + found_a_type = true; } - else + + if (!found_a_type) + { + // Try the modules next. + + do + { + if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) + { + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!modules_decl_vendor->FindDecls(name, + append, + max_matches, + decls)) + break; + + if (log) + { + log->Printf(" CAS::FEVD[%u] Matching entity found for \"%s\" in the modules", + current_id, + name.GetCString()); + } + + clang::NamedDecl *const decl_from_modules = decls[0]; + + if (llvm::isa(decl_from_modules) || + llvm::isa(decl_from_modules) || + llvm::isa(decl_from_modules)) + { + clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); + clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast(copied_decl) : nullptr; + + if (!copied_named_decl) + { + if (log) + log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the modules", + current_id); + + break; + } + + context.AddNamedDecl(copied_named_decl); + + found_a_type = true; + } + } + } while (0); + } + + if (!found_a_type) { do { @@ -753,19 +809,19 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, if (!language_runtime) break; - TypeVendor *type_vendor = language_runtime->GetTypeVendor(); + DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); - if (!type_vendor) + if (!decl_vendor) break; bool append = false; uint32_t max_matches = 1; - std::vector types; + std::vector decls; - if (!type_vendor->FindTypes(name, + if (!decl_vendor->FindDecls(name, append, max_matches, - types)) + decls)) break; if (log) @@ -774,10 +830,11 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, current_id, name.GetCString()); } - - ClangASTType copied_clang_type (GuardedCopyType(types[0])); - - if (!copied_clang_type) + + clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decls[0]->getASTContext(), decls[0]); + clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast(copied_decl) : nullptr; + + if (!copied_named_decl) { if (log) log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the runtime", @@ -786,7 +843,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, break; } - context.AddTypeDecl(copied_clang_type); + context.AddNamedDecl(copied_named_decl); } while(0); } @@ -895,31 +952,44 @@ FindObjCMethodDeclsWithOrigin (unsigned int current_id, } DeclarationName original_decl_name(original_selector); - - ObjCInterfaceDecl::lookup_result result = original_interface_decl->lookup(original_decl_name); - - if (result.empty()) - return false; - - if (!result[0]) + + llvm::SmallVector methods; + + ClangASTContext::GetCompleteDecl(original_ctx, original_interface_decl); + + if (ObjCMethodDecl *instance_method_decl = original_interface_decl->lookupInstanceMethod(original_selector)) + { + methods.push_back(instance_method_decl); + } + else if (ObjCMethodDecl *class_method_decl = original_interface_decl->lookupClassMethod(original_selector)) + { + methods.push_back(class_method_decl); + } + + if (methods.empty()) + { return false; - - for (NamedDecl *named_decl : result) + } + + for (NamedDecl *named_decl : methods) { + if (!named_decl) + continue; + ObjCMethodDecl *result_method = dyn_cast(named_decl); if (!result_method) - return false; + continue; Decl *copied_decl = ast_importer->CopyDecl(ast_context, &result_method->getASTContext(), result_method); if (!copied_decl) - return false; + continue; ObjCMethodDecl *copied_method_decl = dyn_cast(copied_decl); if (!copied_method_decl) - return false; + continue; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -1169,10 +1239,43 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context) return; } while (0); + + do + { + // Check the modules only if the debug information didn't have a complete interface. + + if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) + { + ConstString interface_name(interface_decl->getNameAsString().c_str()); + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!modules_decl_vendor->FindDecls(interface_name, + append, + max_matches, + decls)) + break; + + ObjCInterfaceDecl *interface_decl_from_modules = dyn_cast(decls[0]); + + if (!interface_decl_from_modules) + break; + + if (FindObjCMethodDeclsWithOrigin(current_id, + context, + interface_decl_from_modules, + m_ast_context, + m_ast_importer, + "in modules")) + return; + } + } + while (0); do { - // Check the runtime only if the debug information didn't have a complete interface. + // Check the runtime only if the debug information didn't have a complete interface and the modules don't get us anywhere. lldb::ProcessSP process(m_target->GetProcessSP()); @@ -1184,31 +1287,27 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context) if (!language_runtime) break; - TypeVendor *type_vendor = language_runtime->GetTypeVendor(); + DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); - if (!type_vendor) + if (!decl_vendor) break; ConstString interface_name(interface_decl->getNameAsString().c_str()); bool append = false; uint32_t max_matches = 1; - std::vector types; + std::vector decls; - if (!type_vendor->FindTypes(interface_name, + if (!decl_vendor->FindDecls(interface_name, append, max_matches, - types)) + decls)) break; - const clang::Type *runtime_clang_type = QualType::getFromOpaquePtr(types[0].GetOpaqueQualType()).getTypePtr(); - - const ObjCInterfaceType *runtime_interface_type = dyn_cast(runtime_clang_type); - - if (!runtime_interface_type) + ObjCInterfaceDecl *runtime_interface_decl = dyn_cast(decls[0]); + + if (!runtime_interface_decl) break; - ObjCInterfaceDecl *runtime_interface_decl = runtime_interface_type->getDecl(); - FindObjCMethodDeclsWithOrigin(current_id, context, runtime_interface_decl, @@ -1339,10 +1438,50 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) return; } while(0); + + do + { + // Check the modules only if the debug information didn't have a complete interface. + + ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor(); + + if (!modules_decl_vendor) + break; + + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!modules_decl_vendor->FindDecls(class_name, + append, + max_matches, + decls)) + break; + + DeclFromUser interface_decl_from_modules(dyn_cast(decls[0])); + + if (!interface_decl_from_modules.IsValid()) + break; + + if (log) + log->Printf("CAS::FOPD[%d] trying module (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, + static_cast(interface_decl_from_modules.decl), + static_cast(&interface_decl_from_modules->getASTContext())); + + if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, + context, + *m_ast_context, + m_ast_importer, + interface_decl_from_modules)) + return; + } + while(0); do { - // Check the runtime only if the debug information didn't have a complete interface. + // Check the runtime only if the debug information didn't have a complete interface + // and nothing was in the modules. lldb::ProcessSP process(m_target->GetProcessSP()); @@ -1354,41 +1493,37 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) if (!language_runtime) return; - TypeVendor *type_vendor = language_runtime->GetTypeVendor(); + DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); - if (!type_vendor) + if (!decl_vendor) break; bool append = false; uint32_t max_matches = 1; - std::vector types; + std::vector decls; - if (!type_vendor->FindTypes(class_name, + if (!decl_vendor->FindDecls(class_name, append, max_matches, - types)) + decls)) break; - const clang::Type *runtime_clang_type = QualType::getFromOpaquePtr(types[0].GetOpaqueQualType()).getTypePtr(); - - const ObjCInterfaceType *runtime_interface_type = dyn_cast(runtime_clang_type); - - if (!runtime_interface_type) + DeclFromUser interface_decl_from_runtime(dyn_cast(decls[0])); + + if (!interface_decl_from_runtime.IsValid()) break; - DeclFromUser runtime_iface_decl(runtime_interface_type->getDecl()); - if (log) log->Printf("CAS::FOPD[%d] trying runtime (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", current_id, - static_cast(runtime_iface_decl.decl), - static_cast(&runtime_iface_decl->getASTContext())); + static_cast(interface_decl_from_runtime.decl), + static_cast(&interface_decl_from_runtime->getASTContext())); if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, context, *m_ast_context, m_ast_importer, - runtime_iface_decl)) + interface_decl_from_runtime)) return; } while(0); diff --git a/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp index 43c8a5fb1bcb..e3027378422f 100644 --- a/source/Expression/ClangExpressionDeclMap.cpp +++ b/source/Expression/ClangExpressionDeclMap.cpp @@ -36,6 +36,7 @@ #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/Variable.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/Target/CPPLanguageRuntime.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" @@ -543,6 +544,7 @@ ClangExpressionDeclMap::GetFunctionAddress FindCodeSymbolInContext(name, m_parser_vars->m_sym_ctx, sc_list); uint32_t sc_list_size = sc_list.GetSize(); + if (sc_list_size == 0) { // We occasionally get debug information in which a const function is reported @@ -562,6 +564,25 @@ ClangExpressionDeclMap::GetFunctionAddress sc_list_size = sc_list.GetSize(); } } + + if (sc_list_size == 0) + { + // Sometimes we get a mangled name for a global function that actually should be "extern C." + // This is a hack to compensate. + + const bool is_mangled = true; + Mangled mangled(name, is_mangled); + + CPPLanguageRuntime::MethodName method_name(mangled.GetDemangledName()); + + llvm::StringRef basename = method_name.GetBasename(); + + if (!basename.empty()) + { + FindCodeSymbolInContext(ConstString(basename), m_parser_vars->m_sym_ctx, sc_list); + sc_list_size = sc_list.GetSize(); + } + } for (uint32_t i=0; iGetValueForVariableExpressionPath(name_unique_cstr, eNoDynamicValues, - StackFrame::eExpressionPathOptionCheckPtrVsMember || - StackFrame::eExpressionPathOptionsAllowDirectIVarAccess || - StackFrame::eExpressionPathOptionsNoFragileObjcIvar || - StackFrame::eExpressionPathOptionsNoSyntheticChildren || + StackFrame::eExpressionPathOptionCheckPtrVsMember | + StackFrame::eExpressionPathOptionsNoFragileObjcIvar | + StackFrame::eExpressionPathOptionsNoSyntheticChildren | StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, var, err); @@ -1307,6 +1327,16 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, return; } } + + std::vector decls_from_modules; + + if (target) + { + if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor()) + { + decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules); + } + } if (!context.m_found.variable) { @@ -1384,6 +1414,19 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, non_extern_symbol = sym_ctx.symbol; } } + + if (!context.m_found.function_with_type_info) + { + for (clang::NamedDecl *decl : decls_from_modules) + { + if (llvm::isa(decl)) + { + clang::NamedDecl *copied_decl = llvm::cast(m_ast_importer->CopyDecl(m_ast_context, &decl->getASTContext(), decl)); + context.AddNamedDecl(copied_decl); + context.m_found.function_with_type_info = true; + } + } + } if (!context.m_found.function_with_type_info) { diff --git a/source/Expression/ClangExpressionParser.cpp b/source/Expression/ClangExpressionParser.cpp index f32ca3ae216c..4906108401af 100644 --- a/source/Expression/ClangExpressionParser.cpp +++ b/source/Expression/ClangExpressionParser.cpp @@ -22,6 +22,7 @@ #include "lldb/Expression/ClangASTSource.h" #include "lldb/Expression/ClangExpression.h" #include "lldb/Expression/ClangExpressionDeclMap.h" +#include "lldb/Expression/ClangModulesDeclVendor.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Expression/IRInterpreter.h" @@ -92,6 +93,47 @@ std::string GetBuiltinIncludePath(const char *Argv0) { return P.str(); } +class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks +{ + ClangModulesDeclVendor &m_decl_vendor; + StreamString m_error_stream; + bool m_has_errors = false; +public: + LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor) : + m_decl_vendor(decl_vendor) + { + } + + virtual void moduleImport(SourceLocation import_location, + ModuleIdPath path, + const clang::Module * /*null*/) + { + std::vector string_path; + + for (const std::pair &component : path) + { + string_path.push_back(component.first->getName()); + } + + StreamString error_stream; + + if (!m_decl_vendor.AddModule(string_path, m_error_stream)) + { + m_has_errors = true; + } + } + + bool hasErrors() + { + return m_has_errors; + } + + const std::string &getErrorString() + { + return m_error_stream.GetString(); + } +}; + //===----------------------------------------------------------------------===// // Implementation of ClangExpressionParser //===----------------------------------------------------------------------===// @@ -101,7 +143,8 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, bool generate_debug_info) : m_expr (expr), m_compiler (), - m_code_generator () + m_code_generator (), + m_pp_callbacks(nullptr) { // 1. Create a new compiler instance. m_compiler.reset(new CompilerInstance()); @@ -165,6 +208,7 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, case lldb::eLanguageTypeC_plus_plus: m_compiler->getLangOpts().CPlusPlus = true; m_compiler->getLangOpts().CPlusPlus11 = true; + m_compiler->getHeaderSearchOpts().UseLibcxx = true; break; case lldb::eLanguageTypeObjC_plus_plus: default: @@ -172,6 +216,7 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, m_compiler->getLangOpts().ObjC2 = true; m_compiler->getLangOpts().CPlusPlus = true; m_compiler->getLangOpts().CPlusPlus11 = true; + m_compiler->getHeaderSearchOpts().UseLibcxx = true; break; } @@ -246,7 +291,14 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, m_compiler->createFileManager(); m_compiler->createPreprocessor(TU_Complete); - + + if (ClangModulesDeclVendor *decl_vendor = target_sp->GetClangModulesDeclVendor()) + { + std::unique_ptr pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor)); + m_pp_callbacks = static_cast(pp_callbacks.get()); + m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks)); + } + // 6. Most of this we get from the CompilerInstance, but we // also want to give the context an ExternalASTSource. m_selector_table.reset(new SelectorTable()); @@ -257,6 +309,7 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, m_compiler->getPreprocessor().getIdentifierTable(), *m_selector_table.get(), *m_builtin_context.get())); + ast_context->InitBuiltinTypes(m_compiler->getTarget()); ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); @@ -299,22 +352,23 @@ ClangExpressionParser::Parse (Stream &stream) { std::string temp_source_path; + int temp_fd = -1; + llvm::SmallString result_path; FileSpec tmpdir_file_spec; if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) { - tmpdir_file_spec.AppendPathComponent("expr.XXXXXX"); + tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr"); temp_source_path = std::move(tmpdir_file_spec.GetPath()); + llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path); } else { - temp_source_path = "/tmp/expr.XXXXXX"; + llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path); } - - if (mktemp(&temp_source_path[0])) + + if (temp_fd != -1) { - lldb_private::File file (temp_source_path.c_str(), - File::eOpenOptionWrite | File::eOpenOptionCanCreateNewOnly, - lldb::eFilePermissionsFileDefault); + lldb_private::File file (temp_fd, true); const size_t expr_text_len = strlen(expr_text); size_t bytes_written = expr_text_len; if (file.Write(expr_text, bytes_written).Success()) @@ -323,7 +377,7 @@ ClangExpressionParser::Parse (Stream &stream) { file.Close(); SourceMgr.setMainFileID(SourceMgr.createFileID( - m_file_manager->getFile(temp_source_path), + m_file_manager->getFile(result_path), SourceLocation(), SrcMgr::C_User)); created_main_file = true; } @@ -351,14 +405,19 @@ ClangExpressionParser::Parse (Stream &stream) TextDiagnosticBuffer::const_iterator diag_iterator; int num_errors = 0; + + if (m_pp_callbacks && m_pp_callbacks->hasErrors()) + { + num_errors++; + + stream.PutCString(m_pp_callbacks->getErrorString().c_str()); + } for (diag_iterator = diag_buf->warn_begin(); diag_iterator != diag_buf->warn_end(); ++diag_iterator) stream.Printf("warning: %s\n", (*diag_iterator).second.c_str()); - num_errors = 0; - for (diag_iterator = diag_buf->err_begin(); diag_iterator != diag_buf->err_end(); ++diag_iterator) diff --git a/source/Expression/ClangExpressionVariable.cpp b/source/Expression/ClangExpressionVariable.cpp index c3eae41473e9..e86016e53a7d 100644 --- a/source/Expression/ClangExpressionVariable.cpp +++ b/source/Expression/ClangExpressionVariable.cpp @@ -28,6 +28,17 @@ ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scop { } +ClangExpressionVariable::ClangExpressionVariable (ExecutionContextScope *exe_scope, + Value &value, + const ConstString &name, + uint16_t flags) : + m_parser_vars(), + m_jit_vars (), + m_flags (flags), + m_frozen_sp (ValueObjectConstResult::Create (exe_scope, value, name)) +{ +} + ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &valobj_sp) : m_parser_vars(), m_jit_vars (), diff --git a/source/Expression/ClangFunction.cpp b/source/Expression/ClangFunction.cpp index 27afba2898ab..b438dacdfabc 100644 --- a/source/Expression/ClangFunction.cpp +++ b/source/Expression/ClangFunction.cpp @@ -57,8 +57,8 @@ ClangFunction::ClangFunction const ValueList &arg_value_list, const char *name ) : - m_parser(), m_execution_unit_sp(), + m_parser(), m_jit_module_wp(), m_name (name ? name : ""), m_function_ptr (NULL), @@ -422,7 +422,7 @@ ClangFunction::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_add return true; } -ThreadPlan * +lldb::ThreadPlanSP ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, lldb::addr_t args_addr, const EvaluateExpressionOptions &options, @@ -447,14 +447,14 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, lldb::addr_t args = { args_addr }; - ThreadPlan *new_plan = new ThreadPlanCallFunction (*thread, + lldb::ThreadPlanSP new_plan_sp (new ThreadPlanCallFunction (*thread, wrapper_address, ClangASTType(), args, - options); - new_plan->SetIsMasterPlan(true); - new_plan->SetOkayToDiscard (false); - return new_plan; + options)); + new_plan_sp->SetIsMasterPlan(true); + new_plan_sp->SetOkayToDiscard (false); + return new_plan_sp; } bool @@ -541,10 +541,10 @@ ClangFunction::ExecuteFunction( if (log) log->Printf("== [ClangFunction::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str()); - lldb::ThreadPlanSP call_plan_sp (GetThreadPlanToCallFunction (exe_ctx, - args_addr, - real_options, - errors)); + lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction (exe_ctx, + args_addr, + real_options, + errors); if (!call_plan_sp) return lldb::eExpressionSetupError; diff --git a/source/Expression/ClangModulesDeclVendor.cpp b/source/Expression/ClangModulesDeclVendor.cpp new file mode 100644 index 000000000000..46adaaff33ce --- /dev/null +++ b/source/Expression/ClangModulesDeclVendor.cpp @@ -0,0 +1,372 @@ +//===-- ClangModulesDeclVendor.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/StreamString.h" +#include "lldb/Expression/ClangModulesDeclVendor.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Target/Target.h" + +#include "clang/Basic/TargetInfo.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Parse/Parser.h" +#include "clang/Sema/Lookup.h" +#include "clang/Serialization/ASTReader.h" + +#include + +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. + class StoringDiagnosticConsumer : public clang::DiagnosticConsumer + { + public: + StoringDiagnosticConsumer (); + void + HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info); + + void + ClearDiagnostics (); + + void + DumpDiagnostics (Stream &error_stream); + private: + typedef std::pair IDAndDiagnostic; + std::vector m_diagnostics; + Log * m_log; + }; + + // The private implementation of our ClangModulesDeclVendor. Contains all the Clang state required + // to load modules. + class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor + { + public: + ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr &diagnostics_engine, + llvm::IntrusiveRefCntPtr &compiler_invocation, + std::unique_ptr &&compiler_instance, + std::unique_ptr &&parser); + + virtual bool + AddModule(std::vector &path, + Stream &error_stream); + + virtual uint32_t + FindDecls (const ConstString &name, + bool append, + uint32_t max_matches, + std::vector &decls); + + ~ClangModulesDeclVendorImpl(); + + private: + clang::ModuleLoadResult + DoGetModule(clang::ModuleIdPath path, bool make_visible); + + llvm::IntrusiveRefCntPtr m_diagnostics_engine; + llvm::IntrusiveRefCntPtr m_compiler_invocation; + std::unique_ptr m_compiler_instance; + std::unique_ptr m_parser; + }; +} + +StoringDiagnosticConsumer::StoringDiagnosticConsumer () +{ + m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); +} + +void +StoringDiagnosticConsumer::HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) +{ + llvm::SmallVector diagnostic_string; + + info.FormatDiagnostic(diagnostic_string); + + m_diagnostics.push_back(IDAndDiagnostic(DiagLevel, std::string(diagnostic_string.data(), diagnostic_string.size()))); +} + +void +StoringDiagnosticConsumer::ClearDiagnostics () +{ + m_diagnostics.clear(); +} + +void +StoringDiagnosticConsumer::DumpDiagnostics (Stream &error_stream) +{ + for (IDAndDiagnostic &diag : m_diagnostics) + { + switch (diag.first) + { + default: + error_stream.PutCString(diag.second.c_str()); + error_stream.PutChar('\n'); + break; + case clang::DiagnosticsEngine::Level::Ignored: + break; + } + } +} + +static FileSpec +GetResourceDir () +{ + static FileSpec g_cached_resource_dir; + + static std::once_flag g_once_flag; + + std::call_once(g_once_flag, [](){ + HostInfo::GetLLDBPath (lldb::ePathTypeClangDir, g_cached_resource_dir); + }); + + return g_cached_resource_dir; +} + + +ClangModulesDeclVendor::ClangModulesDeclVendor() +{ +} + +ClangModulesDeclVendor::~ClangModulesDeclVendor() +{ +} + +ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr &diagnostics_engine, + llvm::IntrusiveRefCntPtr &compiler_invocation, + std::unique_ptr &&compiler_instance, + std::unique_ptr &&parser) : + ClangModulesDeclVendor(), + m_diagnostics_engine(diagnostics_engine), + m_compiler_invocation(compiler_invocation), + m_compiler_instance(std::move(compiler_instance)), + m_parser(std::move(parser)) +{ +} + +bool +ClangModulesDeclVendorImpl::AddModule(std::vector &path, + Stream &error_stream) +{ + // Fail early. + + if (m_compiler_instance->hadModuleLoaderFatalFailure()) + { + error_stream.PutCString("error: Couldn't load a module because the module loader is in a fatal state.\n"); + return false; + } + + if (!m_compiler_instance->getPreprocessor().getHeaderSearchInfo().lookupModule(path[0])) + { + error_stream.Printf("error: Header search couldn't locate module %s\n", path[0].str().c_str()); + return false; + } + + llvm::SmallVector, 4> clang_path; + + { + size_t source_loc_counter = 0; + clang::SourceManager &source_manager = m_compiler_instance->getASTContext().getSourceManager(); + + for (llvm::StringRef &component : path) + { + clang_path.push_back(std::make_pair(&m_compiler_instance->getASTContext().Idents.get(component), + source_manager.getLocForStartOfFile(source_manager.getMainFileID()).getLocWithOffset(source_loc_counter++))); + } + } + + StoringDiagnosticConsumer *diagnostic_consumer = static_cast(m_compiler_instance->getDiagnostics().getClient()); + + diagnostic_consumer->ClearDiagnostics(); + + clang::Module *top_level_module = DoGetModule(clang_path.front(), false); + + if (!top_level_module) + { + diagnostic_consumer->DumpDiagnostics(error_stream); + error_stream.Printf("error: Couldn't load top-level module %s\n", path[0].str().c_str()); + return false; + } + + clang::Module *submodule = top_level_module; + + for (size_t ci = 1; ci < path.size(); ++ci) + { + llvm::StringRef &component = path[ci]; + submodule = submodule->findSubmodule(component.str()); + if (!submodule) + { + diagnostic_consumer->DumpDiagnostics(error_stream); + error_stream.Printf("error: Couldn't load submodule %s\n", component.str().c_str()); + return false; + } + } + + clang::Module *requested_module = DoGetModule(clang_path, true); + + return (requested_module != nullptr); +} + +// ClangImporter::lookupValue + +uint32_t +ClangModulesDeclVendorImpl::FindDecls (const ConstString &name, + bool append, + uint32_t max_matches, + std::vector &decls) +{ + if (!append) + decls.clear(); + + clang::IdentifierInfo &ident = m_compiler_instance->getASTContext().Idents.get(name.GetStringRef()); + + clang::LookupResult lookup_result(m_compiler_instance->getSema(), + clang::DeclarationName(&ident), + clang::SourceLocation(), + clang::Sema::LookupOrdinaryName); + + m_compiler_instance->getSema().LookupName(lookup_result, m_compiler_instance->getSema().getScopeForContext(m_compiler_instance->getASTContext().getTranslationUnitDecl())); + + uint32_t num_matches = 0; + + for (clang::NamedDecl *named_decl : lookup_result) + { + if (num_matches >= max_matches) + return num_matches; + + decls.push_back(named_decl); + ++num_matches; + } + + return num_matches; +} + +ClangModulesDeclVendorImpl::~ClangModulesDeclVendorImpl() +{ +} + +clang::ModuleLoadResult +ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path, + bool make_visible) +{ + clang::Module::NameVisibilityKind visibility = make_visible ? clang::Module::AllVisible : clang::Module::Hidden; + + const bool is_inclusion_directive = false; + + return m_compiler_instance->loadModule(path.front().second, path, visibility, is_inclusion_directive); +} + +static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer"; + +lldb_private::ClangModulesDeclVendor * +ClangModulesDeclVendor::Create(Target &target) +{ + // FIXME we should insure programmatically that the expression parser's compiler and the modules runtime's + // compiler are both initialized in the same way – preferably by the same code. + + if (!target.GetPlatform()->SupportsModules()) + return nullptr; + + const ArchSpec &arch = target.GetArchitecture(); + + std::vector compiler_invocation_arguments = + { + "-fmodules", + "-fcxx-modules", + "-fsyntax-only", + "-femit-all-decls", + "-target", arch.GetTriple().str(), + "-fmodules-validate-system-headers", + "-Werror=non-modular-include-in-framework-module" + }; + + target.GetPlatform()->AddClangModuleCompilationOptions(compiler_invocation_arguments); + + compiler_invocation_arguments.push_back(ModuleImportBufferName); + + // Add additional search paths with { "-I", path } or { "-F", path } here. + + { + llvm::SmallString<128> DefaultModuleCache; + const bool erased_on_reboot = false; + llvm::sys::path::system_temp_directory(erased_on_reboot, DefaultModuleCache); + llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang"); + llvm::sys::path::append(DefaultModuleCache, "ModuleCache"); + std::string module_cache_argument("-fmodules-cache-path="); + module_cache_argument.append(DefaultModuleCache.str().str()); + compiler_invocation_arguments.push_back(module_cache_argument); + } + + { + FileSpec clang_resource_dir = GetResourceDir(); + + if (clang_resource_dir.IsDirectory()) + { + compiler_invocation_arguments.push_back("-resource-dir"); + compiler_invocation_arguments.push_back(clang_resource_dir.GetPath()); + } + } + + llvm::IntrusiveRefCntPtr diagnostics_engine = clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions, + new StoringDiagnosticConsumer); + + std::vector compiler_invocation_argument_cstrs; + + for (const std::string &arg : compiler_invocation_arguments) { + compiler_invocation_argument_cstrs.push_back(arg.c_str()); + } + + llvm::IntrusiveRefCntPtr invocation(clang::createInvocationFromCommandLine(compiler_invocation_argument_cstrs, diagnostics_engine)); + + if (!invocation) + return nullptr; + + std::unique_ptr source_buffer = llvm::MemoryBuffer::getMemBuffer("extern int __lldb __attribute__((unavailable));", + ModuleImportBufferName); + + invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName, source_buffer.release()); + + std::unique_ptr instance(new clang::CompilerInstance); + + instance->setDiagnostics(diagnostics_engine.get()); + instance->setInvocation(invocation.get()); + + std::unique_ptr action(new clang::SyntaxOnlyAction); + + instance->setTarget(clang::TargetInfo::CreateTargetInfo(*diagnostics_engine, instance->getInvocation().TargetOpts)); + + if (!instance->hasTarget()) + return nullptr; + + instance->getTarget().adjust(instance->getLangOpts()); + + if (!action->BeginSourceFile(*instance, instance->getFrontendOpts().Inputs[0])) + return nullptr; + + instance->getPreprocessor().enableIncrementalProcessing(); + + instance->createModuleManager(); + + instance->createSema(action->getTranslationUnitKind(), nullptr); + + const bool skipFunctionBodies = false; + std::unique_ptr parser(new clang::Parser(instance->getPreprocessor(), instance->getSema(), skipFunctionBodies)); + + instance->getPreprocessor().EnterMainSourceFile(); + parser->Initialize(); + + clang::Parser::DeclGroupPtrTy parsed; + + while (!parser->ParseTopLevelDecl(parsed)); + + return new ClangModulesDeclVendorImpl (diagnostics_engine, invocation, std::move(instance), std::move(parser)); +} diff --git a/source/Expression/ClangUserExpression.cpp b/source/Expression/ClangUserExpression.cpp index 52ef4d310352..55148462bbc0 100644 --- a/source/Expression/ClangUserExpression.cpp +++ b/source/Expression/ClangUserExpression.cpp @@ -619,15 +619,14 @@ GetObjectPointer (lldb::StackFrameSP frame_sp, valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(), lldb::eNoDynamicValues, - StackFrame::eExpressionPathOptionCheckPtrVsMember || - StackFrame::eExpressionPathOptionsAllowDirectIVarAccess || - StackFrame::eExpressionPathOptionsNoFragileObjcIvar || - StackFrame::eExpressionPathOptionsNoSyntheticChildren || + StackFrame::eExpressionPathOptionCheckPtrVsMember | + StackFrame::eExpressionPathOptionsNoFragileObjcIvar | + StackFrame::eExpressionPathOptionsNoSyntheticChildren | StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, var_sp, err); - if (!err.Success()) + if (!err.Success() || !valobj_sp.get()) return LLDB_INVALID_ADDRESS; lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); @@ -885,17 +884,17 @@ ClangUserExpression::Execute (Stream &error_stream, args.push_back(struct_address); - ThreadPlanCallUserExpression *user_expression_plan = - new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(), - wrapper_address, - args, - options, - shared_ptr_to_me); - lldb::ThreadPlanSP call_plan_sp(user_expression_plan); + lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(), + wrapper_address, + args, + options, + shared_ptr_to_me)); if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream)) return lldb::eExpressionSetupError; + ThreadPlanCallUserExpression *user_expression_plan = static_cast(call_plan_sp.get()); + lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer(); function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize(); @@ -1070,7 +1069,7 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, user_expression_sp, expr_result); - if (options.GetResultIsInternal()) + if (options.GetResultIsInternal() && expr_result && process) { process->GetTarget().GetPersistentVariables().RemovePersistentVariable (expr_result); } diff --git a/source/Expression/DWARFExpression.cpp b/source/Expression/DWARFExpression.cpp index 44b64ab1bf29..827bddd8e7bc 100644 --- a/source/Expression/DWARFExpression.cpp +++ b/source/Expression/DWARFExpression.cpp @@ -2690,11 +2690,6 @@ DWARFExpression::Evaluate } break; - default: - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("unhandled value type for DW_OP_piece(%" PRIu64 ")", piece_byte_size); - return false; - } // Check if this is the first piece? @@ -2880,7 +2875,7 @@ DWARFExpression::Evaluate if (cfa != LLDB_INVALID_ADDRESS) { stack.push_back(Scalar(cfa)); - stack.back().SetValueType (Value::eValueTypeHostAddress); + stack.back().SetValueType (Value::eValueTypeLoadAddress); } else if (error_ptr) diff --git a/source/Expression/IRExecutionUnit.cpp b/source/Expression/IRExecutionUnit.cpp index 090f88fc1bfe..e7cb728778e6 100644 --- a/source/Expression/IRExecutionUnit.cpp +++ b/source/Expression/IRExecutionUnit.cpp @@ -13,6 +13,7 @@ #include "llvm/Support/SourceMgr.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" @@ -199,6 +200,11 @@ IRExecutionUnit::DisassembleFunction (Stream &stream, InstructionList &instruction_list = disassembler_sp->GetInstructionList(); const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize(); + const char *disassemble_format = "${addr-file-or-load}: "; + if (exe_ctx.HasTargetScope()) + { + disassemble_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat(); + } for (size_t instruction_index = 0, num_instructions = instruction_list.GetSize(); instruction_index < num_instructions; @@ -209,7 +215,10 @@ IRExecutionUnit::DisassembleFunction (Stream &stream, max_opcode_byte_size, true, true, - &exe_ctx); + &exe_ctx, + NULL, + NULL, + disassemble_format); stream.PutChar('\n'); } // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions. @@ -300,11 +309,9 @@ IRExecutionUnit::GetRunnableInfo(Error &error, builder.setEngineKind(llvm::EngineKind::JIT) .setErrorStr(&error_string) .setRelocationModel(relocModel) - .setJITMemoryManager(new MemoryManager(*this)) - .setOptLevel(llvm::CodeGenOpt::Less) - .setAllocateGVsWithCode(true) + .setMCJITMemoryManager(std::unique_ptr(new MemoryManager(*this))) .setCodeModel(codeModel) - .setUseMCJIT(true); + .setOptLevel(llvm::CodeGenOpt::Less); llvm::StringRef mArch; llvm::StringRef mCPU; @@ -425,7 +432,7 @@ IRExecutionUnit::~IRExecutionUnit () } IRExecutionUnit::MemoryManager::MemoryManager (IRExecutionUnit &parent) : - m_default_mm_ap (llvm::JITMemoryManager::CreateDefaultMemManager()), + m_default_mm_ap (new llvm::SectionMemoryManager()), m_parent (parent) { } @@ -433,60 +440,6 @@ IRExecutionUnit::MemoryManager::MemoryManager (IRExecutionUnit &parent) : IRExecutionUnit::MemoryManager::~MemoryManager () { } -void -IRExecutionUnit::MemoryManager::setMemoryWritable () -{ - m_default_mm_ap->setMemoryWritable(); -} - -void -IRExecutionUnit::MemoryManager::setMemoryExecutable () -{ - m_default_mm_ap->setMemoryExecutable(); -} - - -uint8_t * -IRExecutionUnit::MemoryManager::startFunctionBody(const llvm::Function *F, - uintptr_t &ActualSize) -{ - return m_default_mm_ap->startFunctionBody(F, ActualSize); -} - -uint8_t * -IRExecutionUnit::MemoryManager::allocateStub(const llvm::GlobalValue* F, - unsigned StubSize, - unsigned Alignment) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - uint8_t *return_value = m_default_mm_ap->allocateStub(F, StubSize, Alignment); - - m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value, - lldb::ePermissionsReadable | lldb::ePermissionsWritable, - GetSectionTypeFromSectionName (llvm::StringRef(), AllocationKind::Stub), - StubSize, - Alignment, - eSectionIDInvalid, - NULL)); - - if (log) - { - log->Printf("IRExecutionUnit::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p", - static_cast(F), StubSize, Alignment, - static_cast(return_value)); - } - - return return_value; -} - -void -IRExecutionUnit::MemoryManager::endFunctionBody(const llvm::Function *F, - uint8_t *FunctionStart, - uint8_t *FunctionEnd) -{ - m_default_mm_ap->endFunctionBody(F, FunctionStart, FunctionEnd); -} lldb::SectionType IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRExecutionUnit::AllocationKind alloc_kind) @@ -597,30 +550,6 @@ IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRE return sect_type; } -uint8_t * -IRExecutionUnit::MemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment); - - m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value, - lldb::ePermissionsReadable | lldb::ePermissionsWritable, - GetSectionTypeFromSectionName (llvm::StringRef(), AllocationKind::Bytes), - Size, - Alignment, - eSectionIDInvalid, - NULL)); - - if (log) - { - log->Printf("IRExecutionUnit::allocateSpace(Size=%" PRIu64 ", Alignment=%u) = %p", - (uint64_t)Size, Alignment, return_value); - } - - return return_value; -} - uint8_t * IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, @@ -675,37 +604,6 @@ IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size, return return_value; } -uint8_t * -IRExecutionUnit::MemoryManager::allocateGlobal(uintptr_t Size, - unsigned Alignment) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment); - - m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value, - lldb::ePermissionsReadable | lldb::ePermissionsWritable, - GetSectionTypeFromSectionName (llvm::StringRef(), AllocationKind::Global), - Size, - Alignment, - eSectionIDInvalid, - NULL)); - - if (log) - { - log->Printf("IRExecutionUnit::allocateGlobal(Size=0x%" PRIx64 ", Alignment=%u) = %p", - (uint64_t)Size, Alignment, return_value); - } - - return return_value; -} - -void -IRExecutionUnit::MemoryManager::deallocateFunctionBody(void *Body) -{ - m_default_mm_ap->deallocateFunctionBody(Body); -} - lldb::addr_t IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address) { diff --git a/source/Expression/IRForTarget.cpp b/source/Expression/IRForTarget.cpp index b91e1b46f88e..8e75c32183ec 100644 --- a/source/Expression/IRForTarget.cpp +++ b/source/Expression/IRForTarget.cpp @@ -18,6 +18,7 @@ #include "llvm/IR/Module.h" #include "llvm/PassManager.h" #include "llvm/Transforms/IPO.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/ValueSymbolTable.h" #include "clang/AST/ASTContext.h" @@ -403,18 +404,17 @@ IRForTarget::DeclForGlobal (const GlobalValue *global_val, Module *module) node_index < num_nodes; ++node_index) { - MDNode *metadata_node = named_metadata->getOperand(node_index); - + llvm::MDNode *metadata_node = dyn_cast(named_metadata->getOperand(node_index)); if (!metadata_node) return NULL; if (metadata_node->getNumOperands() != 2) continue; - if (metadata_node->getOperand(0) != global_val) + if (mdconst::dyn_extract_or_null(metadata_node->getOperand(0)) != global_val) continue; - ConstantInt *constant_int = dyn_cast(metadata_node->getOperand(1)); + ConstantInt *constant_int = mdconst::dyn_extract(metadata_node->getOperand(1)); if (!constant_int) return NULL; @@ -639,11 +639,11 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function) reinterpret_cast(result_decl), false); - llvm::Value* values[2]; - values[0] = new_result_global; - values[1] = new_constant_int; + llvm::Metadata *values[2]; + values[0] = ConstantAsMetadata::get(new_result_global); + values[1] = ConstantAsMetadata::get(new_constant_int); - ArrayRef value_ref(values, 2); + ArrayRef value_ref(values, 2); MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); NamedMDNode *named_metadata = m_module->getNamedMetadata("clang.global.decl.ptrs"); @@ -1037,7 +1037,7 @@ static bool IsObjCSelectorRef (Value *value) { GlobalVariable *global_variable = dyn_cast(value); - if (!global_variable || !global_variable->hasName() || !global_variable->getName().startswith("\01L_OBJC_SELECTOR_REFERENCES_")) + if (!global_variable || !global_variable->hasName() || !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_")) return false; return true; @@ -1056,12 +1056,12 @@ IRForTarget::RewriteObjCSelector (Instruction* selector_load) // Unpack the message name from the selector. In LLVM IR, an objc_msgSend gets represented as // - // %tmp = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_" ; + // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; // %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; // // where %obj is the object pointer and %tmp is the selector. // - // @"\01L_OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_". + // @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_". // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_" contains the string. // Find the pointer's initializer (a ConstantExpr with opcode GetElementPtr) and get the string from its target @@ -1215,7 +1215,7 @@ IRForTarget::RewritePersistentAlloc (llvm::Instruction *persistent_alloc) if (!alloc_md || !alloc_md->getNumOperands()) return false; - ConstantInt *constant_int = dyn_cast(alloc_md->getOperand(0)); + ConstantInt *constant_int = mdconst::dyn_extract(alloc_md->getOperand(0)); if (!constant_int) return false; @@ -1246,11 +1246,11 @@ IRForTarget::RewritePersistentAlloc (llvm::Instruction *persistent_alloc) NamedMDNode *named_metadata = m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs"); - llvm::Value* values[2]; - values[0] = persistent_global; - values[1] = constant_int; + llvm::Metadata *values[2]; + values[0] = ConstantAsMetadata::get(persistent_global); + values[1] = ConstantAsMetadata::get(constant_int); - ArrayRef value_ref(values, 2); + ArrayRef value_ref(values, 2); MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); named_metadata->addOperand(persistent_global_md); @@ -2043,8 +2043,12 @@ static bool isGuardVariableRef(Value *V) GlobalVariable *GV = dyn_cast(Old); - if (!GV || !GV->hasName() || !GV->getName().startswith("_ZGV")) + if (!GV || !GV->hasName() || + (!GV->getName().startswith("_ZGV") && // Itanium ABI guard variable + !GV->getName().endswith("@4IA"))) // Microsoft ABI guard variable + { return false; + } return true; } @@ -2052,20 +2056,8 @@ static bool isGuardVariableRef(Value *V) void IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction* guard_load) { - Constant* zero(ConstantInt::get(Type::getInt8Ty(m_module->getContext()), 0, true)); - - for (llvm::User *u : guard_load->users()) - { - if (isa(u)) - { - // do nothing for the moment - } - else - { - u->replaceUsesOfWith(guard_load, zero); - } - } - + Constant *zero(Constant::getNullValue(guard_load->getType())); + guard_load->replaceAllUsesWith(zero); guard_load->eraseFromParent(); } diff --git a/source/Host/common/Editline.cpp b/source/Host/common/Editline.cpp index 7af9f39a7863..b82fbea90c6c 100644 --- a/source/Host/common/Editline.cpp +++ b/source/Host/common/Editline.cpp @@ -7,527 +7,913 @@ // //===----------------------------------------------------------------------===// +#include +#include +#include #include "lldb/Host/Editline.h" - +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Core/Error.h" -#include "lldb/Core/StreamString.h" #include "lldb/Core/StringList.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" +#include "lldb/Host/Mutex.h" -#include - -using namespace lldb; using namespace lldb_private; +using namespace lldb_private::line_editor; -namespace lldb_private { - typedef std::weak_ptr EditlineHistoryWP; - - - // EditlineHistory objects are sometimes shared between multiple - // Editline instances with the same program name. This class allows - // multiple editline instances to - // - - class EditlineHistory - { - private: - // Use static GetHistory() function to get a EditlineHistorySP to one of these objects - EditlineHistory(const std::string &prefix, uint32_t size, bool unique_entries) : - m_history (NULL), - m_event (), - m_prefix (prefix), - m_path () +// Editline uses careful cursor management to achieve the illusion of editing a multi-line block of text +// with a single line editor. Preserving this illusion requires fairly careful management of cursor +// state. Read and understand the relationship between DisplayInput(), MoveCursor(), SetCurrentLine(), +// and SaveEditedLine() before making changes. + +#define ESCAPE "\x1b" +#define ANSI_FAINT ESCAPE "[2m" +#define ANSI_UNFAINT ESCAPE "[22m" +#define ANSI_CLEAR_BELOW ESCAPE "[J" +#define ANSI_CLEAR_RIGHT ESCAPE "[K" +#define ANSI_SET_COLUMN_N ESCAPE "[%dG" +#define ANSI_UP_N_ROWS ESCAPE "[%dA" +#define ANSI_DOWN_N_ROWS ESCAPE "[%dB" + +#if LLDB_EDITLINE_USE_WCHAR + +#define EditLineConstString(str) L##str +#define EditLineStringFormatSpec "%ls" + +#else + +#define EditLineConstString(str) str +#define EditLineStringFormatSpec "%s" + +// use #defines so wide version functions and structs will resolve to old versions +// for case of libedit not built with wide char support +#define history_w history +#define history_winit history_init +#define history_wend history_end +#define HistoryW History +#define HistEventW HistEvent +#define LineInfoW LineInfo + +#define el_wgets el_gets +#define el_wgetc el_getc +#define el_wpush el_push +#define el_wparse el_parse +#define el_wset el_set +#define el_wget el_get +#define el_wline el_line +#define el_winsertstr el_insertstr +#define el_wdeletestr el_deletestr + +#endif // #if LLDB_EDITLINE_USE_WCHAR + +bool +IsOnlySpaces (const EditLineStringType & content) +{ + for (wchar_t ch : content) + { + if (ch != EditLineCharType(' ')) + return false; + } + return true; +} + +EditLineStringType +CombineLines (const std::vector & lines) +{ + EditLineStringStreamType combined_stream; + for (EditLineStringType line : lines) + { + combined_stream << line.c_str() << "\n"; + } + return combined_stream.str(); +} + +std::vector +SplitLines (const EditLineStringType & input) +{ + std::vector result; + size_t start = 0; + while (start < input.length()) + { + size_t end = input.find ('\n', start); + if (end == std::string::npos) { - m_history = ::history_init(); - ::history (m_history, &m_event, H_SETSIZE, size); - if (unique_entries) - ::history (m_history, &m_event, H_SETUNIQUE, 1); + result.insert (result.end(), input.substr (start)); + break; } + result.insert (result.end(), input.substr (start, end - start)); + start = end + 1; + } + return result; +} + +EditLineStringType +FixIndentation (const EditLineStringType & line, int indent_correction) +{ + if (indent_correction == 0) + return line; + if (indent_correction < 0) + return line.substr (-indent_correction); + return EditLineStringType (indent_correction, EditLineCharType(' ')) + line; +} + +int +GetIndentation (const EditLineStringType & line) +{ + int space_count = 0; + for (EditLineCharType ch : line) + { + if (ch != EditLineCharType(' ')) + break; + ++space_count; + } + return space_count; +} + +bool +IsInputPending (FILE * file) +{ + // FIXME: This will be broken on Windows if we ever re-enable Editline. You can't use select + // on something that isn't a socket. This will have to be re-written to not use a FILE*, but + // instead use some kind of yet-to-be-created abstraction that select-like functionality on + // non-socket objects. + const int fd = fileno (file); + fd_set fds; + FD_ZERO (&fds); + FD_SET (fd, &fds); + timeval timeout = { 0, 0 }; + return select (fd + 1, &fds, NULL, NULL, &timeout); +} + +namespace lldb_private +{ + namespace line_editor + { + typedef std::weak_ptr EditlineHistoryWP; + + // EditlineHistory objects are sometimes shared between multiple + // Editline instances with the same program name. - const char * - GetHistoryFilePath() + class EditlineHistory { - if (m_path.empty() && m_history && !m_prefix.empty()) + private: + // Use static GetHistory() function to get a EditlineHistorySP to one of these objects + EditlineHistory (const std::string &prefix, uint32_t size, bool unique_entries) : + m_history (NULL), + m_event (), + m_prefix (prefix), + m_path () { - char history_path[PATH_MAX]; - ::snprintf (history_path, sizeof(history_path), "~/.%s-history", m_prefix.c_str()); - m_path = std::move(FileSpec(history_path, true).GetPath()); + m_history = history_winit(); + history_w (m_history, &m_event, H_SETSIZE, size); + if (unique_entries) + history_w (m_history, &m_event, H_SETUNIQUE, 1); + } + + const char * + GetHistoryFilePath() + { + if (m_path.empty() && m_history && !m_prefix.empty()) + { + std::string parent_path = FileSpec ("~/.lldb", true).GetPath(); + char history_path[PATH_MAX]; + if (FileSystem::MakeDirectory(parent_path.c_str(), lldb::eFilePermissionsDirectoryDefault).Success()) + { + snprintf (history_path, sizeof (history_path), "~/.lldb/%s-history", m_prefix.c_str()); + } + else + { + snprintf (history_path, sizeof (history_path), "~/%s-widehistory", m_prefix.c_str()); + } + m_path = std::move (FileSpec (history_path, true).GetPath()); + } + if (m_path.empty()) + return NULL; + return m_path.c_str(); } - if (m_path.empty()) - return NULL; - return m_path.c_str(); - } - - public: - - ~EditlineHistory() - { - Save (); - if (m_history) + public: + + ~EditlineHistory() { - ::history_end (m_history); - m_history = NULL; + Save(); + + if (m_history) + { + history_wend (m_history); + m_history = NULL; + } } - } - - static EditlineHistorySP - GetHistory (const std::string &prefix) - { - typedef std::map WeakHistoryMap; - static Mutex g_mutex(Mutex::eMutexTypeRecursive); - static WeakHistoryMap g_weak_map; - Mutex::Locker locker (g_mutex); - WeakHistoryMap::const_iterator pos = g_weak_map.find (prefix); - EditlineHistorySP history_sp; - if (pos != g_weak_map.end()) + + static EditlineHistorySP + GetHistory (const std::string &prefix) { - history_sp = pos->second.lock(); - if (history_sp) - return history_sp; - g_weak_map.erase(pos); + typedef std::map WeakHistoryMap; + static Mutex g_mutex (Mutex::eMutexTypeRecursive); + static WeakHistoryMap g_weak_map; + Mutex::Locker locker (g_mutex); + WeakHistoryMap::const_iterator pos = g_weak_map.find (prefix); + EditlineHistorySP history_sp; + if (pos != g_weak_map.end()) + { + history_sp = pos->second.lock(); + if (history_sp) + return history_sp; + g_weak_map.erase (pos); + } + history_sp.reset (new EditlineHistory (prefix, 800, true)); + g_weak_map[prefix] = history_sp; + return history_sp; } - history_sp.reset(new EditlineHistory(prefix, 800, true)); - g_weak_map[prefix] = history_sp; - return history_sp; - } - - bool IsValid() const - { - return m_history != NULL; - } - - ::History * - GetHistoryPtr () - { - return m_history; - } - - void - Enter (const char *line_cstr) - { - if (m_history) - ::history (m_history, &m_event, H_ENTER, line_cstr); - } - - bool - Load () - { - if (m_history) + + bool IsValid() const { - const char *path = GetHistoryFilePath(); - if (path) + return m_history != NULL; + } + + HistoryW * + GetHistoryPtr () + { + return m_history; + } + + void + Enter (const EditLineCharType *line_cstr) + { + if (m_history) + history_w (m_history, &m_event, H_ENTER, line_cstr); + } + + bool + Load () + { + if (m_history) { - ::history (m_history, &m_event, H_LOAD, path); - return true; + const char *path = GetHistoryFilePath(); + if (path) + { + history_w (m_history, &m_event, H_LOAD, path); + return true; + } } + return false; } - return false; - } - - bool - Save () - { - if (m_history) + + bool + Save () { - const char *path = GetHistoryFilePath(); - if (path) + if (m_history) { - ::history (m_history, &m_event, H_SAVE, path); - return true; + const char *path = GetHistoryFilePath(); + if (path) + { + history_w (m_history, &m_event, H_SAVE, path); + return true; + } } + return false; } - return false; - } - - protected: - ::History *m_history; // The history object - ::HistEvent m_event;// The history event needed to contain all history events - std::string m_prefix; // The prefix name (usually the editline program name) to use when loading/saving history - std::string m_path; // Path to the history file - }; + + protected: + HistoryW * m_history; // The history object + HistEventW m_event; // The history event needed to contain all history events + std::string m_prefix; // The prefix name (usually the editline program name) to use when loading/saving history + std::string m_path; // Path to the history file + }; + } } +//------------------------------------------------------------------ +// Editline private methods +//------------------------------------------------------------------ -static const char k_prompt_escape_char = '\1'; - -Editline::Editline (const char *prog, // prog can't be NULL - const char *prompt, // can be NULL for no prompt - bool configure_for_multiline, - FILE *fin, - FILE *fout, - FILE *ferr) : - m_editline (NULL), - m_history_sp (), - m_prompt (), - m_lines_prompt (), - m_getting_char (false), - m_completion_callback (NULL), - m_completion_callback_baton (NULL), - m_line_complete_callback (NULL), - m_line_complete_callback_baton (NULL), - m_lines_command (Command::None), - m_line_offset (0), - m_lines_curr_line (0), - m_lines_max_line (0), - m_file (fileno(fin), false), - m_prompt_with_line_numbers (false), - m_getting_line (false), - m_got_eof (false), - m_interrupted (false) -{ - if (prog && prog[0]) - { - m_editline = ::el_init(prog, fin, fout, ferr); - - // Get a shared history instance - m_history_sp = EditlineHistory::GetHistory(prog); +void +Editline::SetBaseLineNumber (int line_number) +{ + std::stringstream line_number_stream; + line_number_stream << line_number; + m_base_line_number = line_number; + m_line_number_digits = std::max (3, (int)line_number_stream.str().length() + 1); +} + +std::string +Editline::PromptForIndex (int line_index) +{ + bool use_line_numbers = m_multiline_enabled && m_base_line_number > 0; + std::string prompt = m_set_prompt; + if (use_line_numbers && prompt.length() == 0) + { + prompt = ": "; } - else + std::string continuation_prompt = prompt; + if (m_set_continuation_prompt.length() > 0) { - m_editline = ::el_init("lldb-tmp", fin, fout, ferr); + continuation_prompt = m_set_continuation_prompt; + + // Ensure that both prompts are the same length through space padding + while (continuation_prompt.length() < prompt.length()) + { + continuation_prompt += ' '; + } + while (prompt.length() < continuation_prompt.length()) + { + prompt += ' '; + } } - if (prompt && prompt[0]) - SetPrompt (prompt); + if (use_line_numbers) + { + StreamString prompt_stream; + prompt_stream.Printf("%*d%s", m_line_number_digits, m_base_line_number + line_index, + (line_index == 0) ? prompt.c_str() : continuation_prompt.c_str()); + return std::move (prompt_stream.GetString()); + } + return (line_index == 0) ? prompt : continuation_prompt; +} - //::el_set (m_editline, EL_BIND, "^[[A", NULL); // Print binding for up arrow key - //::el_set (m_editline, EL_BIND, "^[[B", NULL); // Print binding for up down key +void +Editline::SetCurrentLine (int line_index) +{ + m_current_line_index = line_index; + m_current_prompt = PromptForIndex (line_index); +} + +int +Editline::GetPromptWidth() +{ + return (int)PromptForIndex (0).length(); +} - assert (m_editline); - ::el_set (m_editline, EL_CLIENTDATA, this); +bool +Editline::IsEmacs() +{ + const char * editor; + el_get (m_editline, EL_EDITOR, &editor); + return editor[0] == 'e'; +} - // only defined for newer versions of editline -#ifdef EL_PROMPT_ESC - ::el_set (m_editline, EL_PROMPT_ESC, GetPromptCallback, k_prompt_escape_char); -#else - // fall back on old prompt setting code - ::el_set (m_editline, EL_PROMPT, GetPromptCallback); -#endif - ::el_set (m_editline, EL_EDITOR, "emacs"); - if (m_history_sp && m_history_sp->IsValid()) +bool +Editline::IsOnlySpaces() +{ + const LineInfoW * info = el_wline (m_editline); + for (const EditLineCharType * character = info->buffer; character < info->lastchar; character++) { - ::el_set (m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr()); + if (*character != ' ') + return false; } - ::el_set (m_editline, EL_ADDFN, "lldb-complete", "Editline completion function", Editline::CallbackComplete); - // Keep old "lldb_complete" mapping for older clients that used this in their .editrc. editline also - // has a bad bug where if you have a bind command that tries to bind to a function name that doesn't - // exist, it will corrupt the heap and probably crash your process later. - ::el_set (m_editline, EL_ADDFN, "lldb_complete", "Editline completion function", Editline::CallbackComplete); - ::el_set (m_editline, EL_ADDFN, "lldb-edit-prev-line", "Editline edit prev line", Editline::CallbackEditPrevLine); - ::el_set (m_editline, EL_ADDFN, "lldb-edit-next-line", "Editline edit next line", Editline::CallbackEditNextLine); + return true; +} - ::el_set (m_editline, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string - ::el_set (m_editline, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash does. - ::el_set (m_editline, EL_BIND, "\033[3~", "ed-delete-next-char", NULL); // Fix the delete key. - ::el_set (m_editline, EL_BIND, "\t", "lldb-complete", NULL); // Bind TAB to be auto complete - - if (configure_for_multiline) +int +Editline::GetLineIndexForLocation (CursorLocation location, int cursor_row) +{ + int line = 0; + if (location == CursorLocation::EditingPrompt || location == CursorLocation::BlockEnd || + location == CursorLocation::EditingCursor) { - // Use escape sequences for control characters due to bugs in editline - // where "-k up" and "-k down" don't always work. - ::el_set (m_editline, EL_BIND, "^[[A", "lldb-edit-prev-line", NULL); // Map up arrow - ::el_set (m_editline, EL_BIND, "^[[B", "lldb-edit-next-line", NULL); // Map down arrow - // Bindings for next/prev history - ::el_set (m_editline, EL_BIND, "^P", "ed-prev-history", NULL); // Map up arrow - ::el_set (m_editline, EL_BIND, "^N", "ed-next-history", NULL); // Map down arrow + for (unsigned index = 0; index < m_current_line_index; index++) + { + line += CountRowsForLine (m_input_lines[index]); + } + if (location == CursorLocation::EditingCursor) + { + line += cursor_row; + } + else if (location == CursorLocation::BlockEnd) + { + for (unsigned index = m_current_line_index; index < m_input_lines.size(); index++) + { + line += CountRowsForLine (m_input_lines[index]); + } + --line; + } } - else + return line; +} + +void +Editline::MoveCursor (CursorLocation from, CursorLocation to) +{ + const LineInfoW * info = el_wline (m_editline); + int editline_cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth()); + int editline_cursor_row = editline_cursor_position / m_terminal_width; + + // Determine relative starting and ending lines + int fromLine = GetLineIndexForLocation (from, editline_cursor_row); + int toLine = GetLineIndexForLocation (to, editline_cursor_row); + if (toLine != fromLine) { - // Use escape sequences for control characters due to bugs in editline - // where "-k up" and "-k down" don't always work. - ::el_set (m_editline, EL_BIND, "^[[A", "ed-prev-history", NULL); // Map up arrow - ::el_set (m_editline, EL_BIND, "^[[B", "ed-next-history", NULL); // Map down arrow + fprintf (m_output_file, (toLine > fromLine) ? ANSI_DOWN_N_ROWS : ANSI_UP_N_ROWS, std::abs (toLine - fromLine)); } - // Source $PWD/.editrc then $HOME/.editrc - ::el_source (m_editline, NULL); - - // Always read through our callback function so we don't read - // stuff we aren't supposed to. This also stops the extra echoing - // that can happen when you have more input than editline can handle - // at once. - SetGetCharCallback(GetCharFromInputFileCallback); - - LoadHistory(); + // Determine target column + int toColumn = 1; + if (to == CursorLocation::EditingCursor) + { + toColumn = editline_cursor_position - (editline_cursor_row * m_terminal_width) + 1; + } + else if (to == CursorLocation::BlockEnd) + { + toColumn = ((m_input_lines[m_input_lines.size() - 1].length() + GetPromptWidth()) % 80) + 1; + } + fprintf (m_output_file, ANSI_SET_COLUMN_N, toColumn); } -Editline::~Editline() +void +Editline::DisplayInput (int firstIndex) { - // EditlineHistory objects are sometimes shared between multiple - // Editline instances with the same program name. So just release - // our shared pointer and if we are the last owner, it will save the - // history to the history save file automatically. - m_history_sp.reset(); + fprintf (m_output_file, ANSI_SET_COLUMN_N ANSI_CLEAR_BELOW, 1); + int line_count = (int)m_input_lines.size(); + const char *faint = m_color_prompts ? ANSI_FAINT : ""; + const char *unfaint = m_color_prompts ? ANSI_UNFAINT : ""; - // Disable edit mode to stop the terminal from flushing all input - // during the call to el_end() since we expect to have multiple editline - // instances in this program. - ::el_set (m_editline, EL_EDITMODE, 0); + for (int index = firstIndex; index < line_count; index++) + { + fprintf (m_output_file, "%s" "%s" "%s" EditLineStringFormatSpec " ", + faint, + PromptForIndex (index).c_str(), + unfaint, + m_input_lines[index].c_str()); + if (index < line_count - 1) + fprintf (m_output_file, "\n"); + } +} - ::el_end(m_editline); - m_editline = NULL; + +int +Editline::CountRowsForLine (const EditLineStringType & content) +{ + auto prompt = PromptForIndex (0); // Prompt width is constant during an edit session + int line_length = (int)(content.length() + prompt.length()); + return (line_length / m_terminal_width) + 1; } void -Editline::SetGetCharCallback (GetCharCallbackType callback) +Editline::SaveEditedLine() { - ::el_set (m_editline, EL_GETCFN, callback); + const LineInfoW * info = el_wline (m_editline); + m_input_lines[m_current_line_index] = EditLineStringType (info->buffer, info->lastchar - info->buffer); } -bool -Editline::LoadHistory () +StringList +Editline::GetInputAsStringList(int line_count) { - if (m_history_sp) - return m_history_sp->Load(); - return false; + StringList lines; + for (EditLineStringType line : m_input_lines) + { + if (line_count == 0) + break; +#if LLDB_EDITLINE_USE_WCHAR + lines.AppendString (m_utf8conv.to_bytes (line)); +#else + lines.AppendString(line); +#endif + --line_count; + } + return lines; } -bool -Editline::SaveHistory () +unsigned char +Editline::RecallHistory (bool earlier) { - if (m_history_sp) - return m_history_sp->Save(); - return false; -} + if (!m_history_sp || !m_history_sp->IsValid()) + return CC_ERROR; + + HistoryW * pHistory = m_history_sp->GetHistoryPtr(); + HistEventW history_event; + std::vector new_input_lines; + + // Treat moving from the "live" entry differently + if (!m_in_history) + { + if (earlier == false) + return CC_ERROR; // Can't go newer than the "live" entry + if (history_w (pHistory, &history_event, H_FIRST) == -1) + return CC_ERROR; + + // Save any edits to the "live" entry in case we return by moving forward in history + // (it would be more bash-like to save over any current entry, but libedit doesn't + // offer the ability to add entries anywhere except the end.) + SaveEditedLine(); + m_live_history_lines = m_input_lines; + m_in_history = true; + } + else + { + if (history_w (pHistory, &history_event, earlier ? H_NEXT : H_PREV) == -1) + { + // Can't move earlier than the earliest entry + if (earlier) + return CC_ERROR; + // ... but moving to newer than the newest yields the "live" entry + new_input_lines = m_live_history_lines; + m_in_history = false; + } + } + + // If we're pulling the lines from history, split them apart + if (m_in_history) + new_input_lines = SplitLines (history_event.str); -Error -Editline::PrivateGetLine(std::string &line) + // Erase the current edit session and replace it with a new one + MoveCursor (CursorLocation::EditingCursor, CursorLocation::BlockStart); + m_input_lines = new_input_lines; + DisplayInput(); + + // Prepare to edit the last line when moving to previous entry, or the first line + // when moving to next entry + SetCurrentLine (m_current_line_index = earlier ? (int)m_input_lines.size() - 1 : 0); + MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt); + return CC_NEWLINE; +} + +int +Editline::GetCharacter (EditLineCharType * c) { - Error error; - if (m_interrupted) + const LineInfoW * info = el_wline (m_editline); + + // Paint a faint version of the desired prompt over the version libedit draws + // (will only be requested if colors are supported) + if (m_needs_prompt_repaint) { - error.SetErrorString("interrupted"); - return error; + MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + fprintf (m_output_file, "%s" "%s" "%s", ANSI_FAINT, Prompt(), ANSI_UNFAINT); + MoveCursor (CursorLocation::EditingPrompt, CursorLocation::EditingCursor); + m_needs_prompt_repaint = false; } - line.clear(); - if (m_editline != NULL) + if (m_multiline_enabled) { - int line_len = 0; - // Call el_gets to prompt the user and read the user's input. - const char *line_cstr = ::el_gets (m_editline, &line_len); - - static int save_errno = (line_len < 0) ? errno : 0; - - if (save_errno != 0) + // Detect when the number of rows used for this input line changes due to an edit + int lineLength = (int)((info->lastchar - info->buffer) + GetPromptWidth()); + int new_line_rows = (lineLength / m_terminal_width) + 1; + if (m_current_line_rows != -1 && new_line_rows != m_current_line_rows) { - error.SetError(save_errno, eErrorTypePOSIX); + // Respond by repainting the current state from this line on + MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + SaveEditedLine(); + DisplayInput (m_current_line_index); + MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingCursor); } - else if (line_cstr) + m_current_line_rows = new_line_rows; + } + + // Read an actual character + while (true) + { + lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess; + char ch = 0; + m_editor_getting_char = true; + int read_count = m_input_connection.Read(&ch, 1, UINT32_MAX, status, NULL); + m_editor_getting_char = false; + if (read_count) { - // Decrement the length so we don't have newline characters in "line" for when - // we assign the cstr into the std::string - llvm::StringRef line_ref (line_cstr); - line_ref = line_ref.rtrim("\n\r"); - - if (!line_ref.empty() && !m_interrupted) +#if LLDB_EDITLINE_USE_WCHAR + // After the initial interruptible read, this is guaranteed not to block + ungetc (ch, m_input_file); + *c = fgetwc (m_input_file); + if (*c != WEOF) + return 1; +#else + *c = ch; + if(*c != EOF) + return 1; +#endif + } + else + { + switch (status) { - // We didn't strip the newlines, we just adjusted the length, and - // we want to add the history item with the newlines - if (m_history_sp) - m_history_sp->Enter(line_cstr); - - // Copy the part of the c string that we want (removing the newline chars) - line = std::move(line_ref.str()); + case lldb::eConnectionStatusInterrupted: + m_editor_status = EditorStatus::Interrupted; + printf ("^C\n"); + return 0; + + case lldb::eConnectionStatusSuccess: // Success + break; + + case lldb::eConnectionStatusError: // Check GetError() for details + case lldb::eConnectionStatusTimedOut: // Request timed out + case lldb::eConnectionStatusEndOfFile: // End-of-file encountered + case lldb::eConnectionStatusNoConnection: // No connection + case lldb::eConnectionStatusLostConnection: // Lost connection while connected to a valid connection + m_editor_status = EditorStatus::EndOfInput; + return 0; } } } - else - { - error.SetErrorString("the EditLine instance has been deleted"); - } - return error; } +const char * +Editline::Prompt() +{ + if (m_color_prompts) + m_needs_prompt_repaint = true; + return m_current_prompt.c_str(); +} -Error -Editline::GetLine(std::string &line, bool &interrupted) +unsigned char +Editline::BreakLineCommand (int ch) { - Error error; - interrupted = false; - line.clear(); + // Preserve any content beyond the cursor, truncate and save the current line + const LineInfoW * info = el_wline (m_editline); + auto current_line = EditLineStringType (info->buffer, info->cursor - info->buffer); + auto new_line_fragment = EditLineStringType (info->cursor, info->lastchar - info->cursor); + m_input_lines[m_current_line_index] = current_line; + + // Ignore whitespace-only extra fragments when breaking a line + if (::IsOnlySpaces (new_line_fragment)) + new_line_fragment = EditLineConstString(""); - // Set arrow key bindings for up and down arrows for single line - // mode where up and down arrows do prev/next history - m_interrupted = false; + // Establish the new cursor position at the start of a line when inserting a line break + m_revert_cursor_index = 0; - if (!m_got_eof) + // Don't perform end of input detection or automatic formatting when pasting + if (!IsInputPending (m_input_file)) { - if (m_getting_line) + // If this is the end of the last line, treat this as a potential exit + if (m_current_line_index == m_input_lines.size() - 1 && new_line_fragment.length() == 0) { - error.SetErrorString("already getting a line"); - return error; + bool end_of_input = true; + if (m_is_input_complete_callback) + { + SaveEditedLine(); + auto lines = GetInputAsStringList(); + end_of_input = m_is_input_complete_callback (this, lines, m_is_input_complete_callback_baton); + + // The completion test is allowed to change the input lines when complete + if (end_of_input) + { + m_input_lines.clear(); + for (unsigned index = 0; index < lines.GetSize(); index++) + { +#if LLDB_EDITLINE_USE_WCHAR + m_input_lines.insert (m_input_lines.end(), m_utf8conv.from_bytes (lines[index])); +#else + m_input_lines.insert (m_input_lines.end(), lines[index]); +#endif + } + } + } + if (end_of_input) + { + fprintf (m_output_file, "\n"); + m_editor_status = EditorStatus::Complete; + return CC_NEWLINE; + } } - if (m_lines_curr_line > 0) + + // Apply smart indentation + if (m_fix_indentation_callback) { - error.SetErrorString("already getting lines"); - return error; + StringList lines = GetInputAsStringList (m_current_line_index + 1); +#if LLDB_EDITLINE_USE_WCHAR + lines.AppendString (m_utf8conv.to_bytes (new_line_fragment)); +#else + lines.AppendString (new_line_fragment); +#endif + + int indent_correction = m_fix_indentation_callback (this, lines, 0, m_fix_indentation_callback_baton); + new_line_fragment = FixIndentation(new_line_fragment, indent_correction); + m_revert_cursor_index = GetIndentation(new_line_fragment); } - m_getting_line = true; - error = PrivateGetLine(line); - m_getting_line = false; } + + // Insert the new line and repaint everything from the split line on down + m_input_lines.insert (m_input_lines.begin() + m_current_line_index + 1, new_line_fragment); + MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + DisplayInput (m_current_line_index); + + // Reposition the cursor to the right line and prepare to edit the new line + SetCurrentLine (m_current_line_index + 1); + MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt); + return CC_NEWLINE; +} - interrupted = m_interrupted; - - if (m_got_eof && line.empty()) +unsigned char +Editline::DeleteNextCharCommand (int ch) +{ + LineInfoW * info = (LineInfoW *)el_wline (m_editline); + + // Just delete the next character normally if possible + if (info->cursor < info->lastchar) { - // Only set the error if we didn't get an error back from PrivateGetLine() - if (error.Success()) - error.SetErrorString("end of file"); + info->cursor++; + el_deletestr (m_editline, 1); + return CC_REFRESH; } - return error; + // Fail when at the end of the last line, except when ^D is pressed on + // the line is empty, in which case it is treated as EOF + if (m_current_line_index == m_input_lines.size() - 1) + { + if (ch == 4 && info->buffer == info->lastchar) + { + fprintf (m_output_file, "^D\n"); + m_editor_status = EditorStatus::EndOfInput; + return CC_EOF; + } + return CC_ERROR; + } + + // Prepare to combine this line with the one below + MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + + // Insert the next line of text at the cursor and restore the cursor position + const EditLineCharType * cursor = info->cursor; + el_winsertstr (m_editline, m_input_lines[m_current_line_index + 1].c_str()); + info->cursor = cursor; + SaveEditedLine(); + + // Delete the extra line + m_input_lines.erase (m_input_lines.begin() + m_current_line_index + 1); + + // Clear and repaint from this line on down + DisplayInput (m_current_line_index); + MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingCursor); + return CC_REFRESH; } -size_t -Editline::Push (const char *bytes, size_t len) +unsigned char +Editline::DeletePreviousCharCommand (int ch) { - if (m_editline) + LineInfoW * info = (LineInfoW *)el_wline (m_editline); + + // Just delete the previous character normally when not at the start of a line + if (info->cursor > info->buffer) { - // Must NULL terminate the string for el_push() so we stick it - // into a std::string first - ::el_push(m_editline, - const_cast(std::string (bytes, len).c_str())); - return len; + el_deletestr (m_editline, 1); + return CC_REFRESH; } - return 0; + + // No prior line and no prior character? Let the user know + if (m_current_line_index == 0) + return CC_ERROR; + + // No prior character, but prior line? Combine with the line above + SaveEditedLine(); + SetCurrentLine (m_current_line_index - 1); + auto priorLine = m_input_lines[m_current_line_index]; + m_input_lines.erase (m_input_lines.begin() + m_current_line_index); + m_input_lines[m_current_line_index] = priorLine + m_input_lines[m_current_line_index]; + + // Repaint from the new line down + fprintf (m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N, CountRowsForLine (priorLine), 1); + DisplayInput (m_current_line_index); + + // Put the cursor back where libedit expects it to be before returning to editing + // by telling libedit about the newly inserted text + MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt); + el_winsertstr (m_editline, priorLine.c_str()); + return CC_REDISPLAY; } - -Error -Editline::GetLines(const std::string &end_line, StringList &lines, bool &interrupted) +unsigned char +Editline::PreviousLineCommand (int ch) { - Error error; - interrupted = false; - if (m_getting_line) - { - error.SetErrorString("already getting a line"); - return error; + SaveEditedLine(); + + if (m_current_line_index == 0) { + return RecallHistory (true); } - if (m_lines_curr_line > 0) + + // Start from a known location + MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + + // Treat moving up from a blank last line as a deletion of that line + if (m_current_line_index == m_input_lines.size() - 1 && IsOnlySpaces()) { - error.SetErrorString("already getting lines"); - return error; + m_input_lines.erase (m_input_lines.begin() + m_current_line_index); + fprintf (m_output_file, ANSI_CLEAR_BELOW); } - // Set arrow key bindings for up and down arrows for multiple line - // mode where up and down arrows do edit prev/next line - m_interrupted = false; - - LineStatus line_status = LineStatus::Success; + SetCurrentLine (m_current_line_index - 1); + fprintf (m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N, + CountRowsForLine (m_input_lines[m_current_line_index]), 1); + return CC_NEWLINE; +} - lines.Clear(); +unsigned char +Editline::NextLineCommand (int ch) +{ + SaveEditedLine(); - FILE *out_file = GetOutputFile(); - FILE *err_file = GetErrorFile(); - m_lines_curr_line = 1; - while (line_status != LineStatus::Done) + // Handle attempts to move down from the last line + if (m_current_line_index == m_input_lines.size() - 1) { - const uint32_t line_idx = m_lines_curr_line-1; - if (line_idx >= lines.GetSize()) - lines.SetSize(m_lines_curr_line); - m_lines_max_line = lines.GetSize(); - m_lines_command = Command::None; - assert(line_idx < m_lines_max_line); - std::string &line = lines[line_idx]; - error = PrivateGetLine(line); - if (error.Fail()) + // Don't add an extra line if the existing last line is blank, move through history instead + if (IsOnlySpaces()) { - line_status = LineStatus::Error; + return RecallHistory (false); } - else if (m_interrupted) + + // Determine indentation for the new line + int indentation = 0; + if (m_fix_indentation_callback) { - interrupted = true; - line_status = LineStatus::Done; + StringList lines = GetInputAsStringList(); + lines.AppendString(""); + indentation = m_fix_indentation_callback (this, lines, 0, m_fix_indentation_callback_baton); } - else - { - switch (m_lines_command) - { - case Command::None: - if (m_line_complete_callback) - { - line_status = m_line_complete_callback (this, - lines, - line_idx, - error, - m_line_complete_callback_baton); - } - else if (line == end_line) - { - line_status = LineStatus::Done; - } + m_input_lines.insert (m_input_lines.end(), EditLineStringType (indentation, EditLineCharType(' '))); + } + + // Move down past the current line using newlines to force scrolling if needed + SetCurrentLine (m_current_line_index + 1); + const LineInfoW * info = el_wline (m_editline); + int cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth()); + int cursor_row = cursor_position / m_terminal_width; + for (int line_count = 0; line_count < m_current_line_rows - cursor_row; line_count++) + { + fprintf (m_output_file, "\n"); + } + return CC_NEWLINE; +} - if (line_status == LineStatus::Success) - { - ++m_lines_curr_line; - // If we already have content for the next line because - // we were editing previous lines, then populate the line - // with the appropriate contents - if (line_idx+1 < lines.GetSize() && !lines[line_idx+1].empty()) - ::el_push (m_editline, - const_cast(lines[line_idx+1].c_str())); - } - else if (line_status == LineStatus::Error) - { - // Clear to end of line ("ESC[K"), then print the error, - // then go to the next line ("\n") and then move cursor up - // two lines ("ESC[2A"). - fprintf (err_file, "\033[Kerror: %s\n\033[2A", error.AsCString()); - } - break; - case Command::EditPrevLine: - if (m_lines_curr_line > 1) - { - //::fprintf (out_file, "\033[1A\033[%uD\033[2K", (uint32_t)(m_lines_prompt.size() + lines[line_idx].size())); // Make cursor go up a line and clear that line - ::fprintf (out_file, "\033[1A\033[1000D\033[2K"); - if (!lines[line_idx-1].empty()) - ::el_push (m_editline, - const_cast(lines[line_idx-1].c_str())); - --m_lines_curr_line; - } - break; - case Command::EditNextLine: - // Allow the down arrow to create a new line - ++m_lines_curr_line; - //::fprintf (out_file, "\033[1B\033[%uD\033[2K", (uint32_t)(m_lines_prompt.size() + lines[line_idx].size())); - ::fprintf (out_file, "\033[1B\033[1000D\033[2K"); - if (line_idx+1 < lines.GetSize() && !lines[line_idx+1].empty()) - ::el_push (m_editline, - const_cast(lines[line_idx+1].c_str())); - break; - } +unsigned char +Editline::FixIndentationCommand (int ch) +{ + if (!m_fix_indentation_callback) + return CC_NORM; + + // Insert the character by hand prior to correction + EditLineCharType inserted[] = { (EditLineCharType)ch, 0 }; + el_winsertstr (m_editline, inserted); + SaveEditedLine(); + StringList lines = GetInputAsStringList (m_current_line_index + 1); + + // Determine the cursor position + LineInfoW * info = (LineInfoW *)el_wline (m_editline); + int cursor_position = info->cursor - info->buffer; + + int indent_correction = m_fix_indentation_callback (this, lines, cursor_position, m_fix_indentation_callback_baton); + + // Adjust the input buffer to correct indentation + if (indent_correction > 0) + { + info->cursor = info->buffer; + el_winsertstr (m_editline, EditLineStringType (indent_correction, EditLineCharType(' ')).c_str()); + } + else if (indent_correction < 0) + { + info->cursor = info->buffer - indent_correction; + el_wdeletestr (m_editline, -indent_correction); + } + info->cursor = info->buffer + cursor_position + indent_correction; + return CC_REFRESH; +} + +unsigned char +Editline::RevertLineCommand (int ch) +{ + el_winsertstr (m_editline, m_input_lines[m_current_line_index].c_str()); + if (m_revert_cursor_index >= 0) + { + LineInfoW * info = (LineInfoW *)el_wline (m_editline); + info->cursor = info->buffer + m_revert_cursor_index; + if (info->cursor > info->lastchar) + { + info->cursor = info->lastchar; } + m_revert_cursor_index = -1; } - m_lines_curr_line = 0; - m_lines_command = Command::None; + return CC_REFRESH; +} - // If we have a callback, call it one more time to let the - // user know the lines are complete - if (m_line_complete_callback && !interrupted) - m_line_complete_callback (this, - lines, - UINT32_MAX, - error, - m_line_complete_callback_baton); +unsigned char +Editline::BufferStartCommand (int ch) +{ + SaveEditedLine(); + MoveCursor (CursorLocation::EditingCursor, CursorLocation::BlockStart); + SetCurrentLine (0); + m_revert_cursor_index = 0; + return CC_NEWLINE; +} - return error; +unsigned char +Editline::BufferEndCommand (int ch) +{ + SaveEditedLine(); + MoveCursor (CursorLocation::EditingCursor, CursorLocation::BlockEnd); + SetCurrentLine ((int)m_input_lines.size() - 1); + MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt); + return CC_NEWLINE; } unsigned char -Editline::HandleCompletion (int ch) +Editline::TabCommand (int ch) { - if (m_completion_callback == NULL) + if (m_completion_callback == nullptr) return CC_ERROR; - - const LineInfo *line_info = ::el_line(m_editline); + + const LineInfo *line_info = el_line (m_editline); StringList completions; int page_size = 40; - + const int num_completions = m_completion_callback (line_info->buffer, line_info->cursor, line_info->lastchar, @@ -536,25 +922,25 @@ Editline::HandleCompletion (int ch) completions, m_completion_callback_baton); - FILE *out_file = GetOutputFile(); - -// if (num_completions == -1) -// { -// ::el_insertstr (m_editline, m_completion_key); -// return CC_REDISPLAY; -// } -// else + if (num_completions == 0) + return CC_ERROR; + // if (num_completions == -1) + // { + // el_insertstr (m_editline, m_completion_key); + // return CC_REDISPLAY; + // } + // else if (num_completions == -2) { // Replace the entire line with the first string... - ::el_deletestr (m_editline, line_info->cursor - line_info->buffer); - ::el_insertstr (m_editline, completions.GetStringAtIndex(0)); + el_deletestr (m_editline, line_info->cursor - line_info->buffer); + el_insertstr (m_editline, completions.GetStringAtIndex (0)); return CC_REDISPLAY; } // If we get a longer match display that first. - const char *completion_str = completions.GetStringAtIndex(0); - if (completion_str != NULL && *completion_str != '\0') + const char *completion_str = completions.GetStringAtIndex (0); + if (completion_str != nullptr && *completion_str != '\0') { el_insertstr (m_editline, completion_str); return CC_REDISPLAY; @@ -563,15 +949,15 @@ Editline::HandleCompletion (int ch) if (num_completions > 1) { int num_elements = num_completions + 1; - ::fprintf (out_file, "\nAvailable completions:"); + fprintf (m_output_file, "\n" ANSI_CLEAR_BELOW "Available completions:"); if (num_completions < page_size) { for (int i = 1; i < num_elements; i++) { - completion_str = completions.GetStringAtIndex(i); - ::fprintf (out_file, "\n\t%s", completion_str); + completion_str = completions.GetStringAtIndex (i); + fprintf (m_output_file, "\n\t%s", completion_str); } - ::fprintf (out_file, "\n"); + fprintf (m_output_file, "\n"); } else { @@ -585,17 +971,17 @@ Editline::HandleCompletion (int ch) endpoint = num_elements; for (; cur_pos < endpoint; cur_pos++) { - completion_str = completions.GetStringAtIndex(cur_pos); - ::fprintf (out_file, "\n\t%s", completion_str); + completion_str = completions.GetStringAtIndex (cur_pos); + fprintf (m_output_file, "\n\t%s", completion_str); } if (cur_pos >= num_elements) { - ::fprintf (out_file, "\n"); + fprintf (m_output_file, "\n"); break; } - ::fprintf (out_file, "\nMore (Y/n/a): "); + fprintf (m_output_file, "\nMore (Y/n/a): "); reply = 'n'; got_char = el_getc(m_editline, &reply); if (got_char == -1 || reply == 'n') @@ -604,247 +990,388 @@ Editline::HandleCompletion (int ch) page_size = num_elements - cur_pos; } } - + DisplayInput(); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); } - - if (num_completions == 0) - return CC_REFRESH_BEEP; - else - return CC_REDISPLAY; + return CC_REDISPLAY; } -Editline * -Editline::GetClientData (::EditLine *e) +void +Editline::ConfigureEditor (bool multiline) { - Editline *editline = NULL; - if (e && ::el_get(e, EL_CLIENTDATA, &editline) == 0) - return editline; - return NULL; -} + if (m_editline && m_multiline_enabled == multiline) + return; + m_multiline_enabled = multiline; + + if (m_editline) + { + // Disable edit mode to stop the terminal from flushing all input + // during the call to el_end() since we expect to have multiple editline + // instances in this program. + el_set (m_editline, EL_EDITMODE, 0); + el_end (m_editline); + } + + m_editline = el_init (m_editor_name.c_str(), m_input_file, m_output_file, m_error_file); + TerminalSizeChanged(); + + if (m_history_sp && m_history_sp->IsValid()) + { + m_history_sp->Load(); + el_wset (m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr()); + } + 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(); + })); -FILE * -Editline::GetInputFile () -{ - return GetFilePointer (m_editline, 0); + el_wset (m_editline, EL_GETCFN, + (EditlineGetCharCallbackType)([] (EditLine * editline, EditLineCharType * c) { + return Editline::InstanceFor (editline)->GetCharacter (c); + })); + + // Commands used for multiline support, registered whether or not they're used + el_set (m_editline, EL_ADDFN, "lldb-break-line", "Insert a line break", + (EditlineCommandCallbackType)([] (EditLine * editline, int ch) { + return Editline::InstanceFor (editline)->BreakLineCommand (ch); + })); + el_set (m_editline, EL_ADDFN, "lldb-delete-next-char", "Delete next character", + (EditlineCommandCallbackType)([] (EditLine * editline, int ch) { + return Editline::InstanceFor (editline)->DeleteNextCharCommand (ch); + })); + el_set (m_editline, EL_ADDFN, "lldb-delete-previous-char", "Delete previous character", + (EditlineCommandCallbackType)([] (EditLine * editline, int ch) { + return Editline::InstanceFor (editline)->DeletePreviousCharCommand (ch); + })); + el_set (m_editline, EL_ADDFN, "lldb-previous-line", "Move to previous line", + (EditlineCommandCallbackType)([] (EditLine * editline, int ch) { + return Editline::InstanceFor (editline)->PreviousLineCommand (ch); + })); + el_set (m_editline, EL_ADDFN, "lldb-next-line", "Move to next line", + (EditlineCommandCallbackType)([] (EditLine * editline, int ch) { + return Editline::InstanceFor (editline)->NextLineCommand (ch); + })); + el_set (m_editline, EL_ADDFN, "lldb-buffer-start", "Move to start of buffer", + (EditlineCommandCallbackType)([] (EditLine * editline, int ch) { + return Editline::InstanceFor (editline)->BufferStartCommand (ch); + })); + el_set (m_editline, EL_ADDFN, "lldb-buffer-end", "Move to end of buffer", + (EditlineCommandCallbackType)([] (EditLine * editline, int ch) { + return Editline::InstanceFor (editline)->BufferEndCommand (ch); + })); + el_set (m_editline, EL_ADDFN, "lldb-fix-indentation", "Fix line indentation", + (EditlineCommandCallbackType)([] (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 becuase libedit has a bad bug where if you have a bind command + // that tries to bind to a function name that doesn't exist, it can corrupt the heap and + // crash your process later.) + EditlineCommandCallbackType complete_callback = [] (EditLine * editline, int ch) { + return Editline::InstanceFor (editline)->TabCommand (ch); + }; + el_set (m_editline, EL_ADDFN, "lldb-complete", "Invoke completion", complete_callback); + el_set (m_editline, EL_ADDFN, "lldb_complete", "Invoke completion", complete_callback); + + // General bindings we don't mind being overridden + if (!multiline) { + el_set (m_editline, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string + } + el_set (m_editline, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash in emacs mode + el_set (m_editline, EL_BIND, "\t", "lldb-complete", NULL); // Bind TAB to auto complete + + // Allow user-specific customization prior to registering bindings we absolutely require + el_source (m_editline, NULL); + + // Register an internal binding that external developers shouldn't use + el_set (m_editline, EL_ADDFN, "lldb-revert-line", "Revert line to saved state", + (EditlineCommandCallbackType)([] (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) + { + char bind_key[2] = { 0, 0 }; + const char * indent_chars = m_fix_indentation_callback_chars; + while (*indent_chars) + { + bind_key[0] = *indent_chars; + el_set (m_editline, EL_BIND, bind_key, "lldb-fix-indentation", NULL); + ++indent_chars; + } + } + + // Multi-line editor bindings + if (multiline) + { + el_set (m_editline, EL_BIND, "\n", "lldb-break-line", NULL); + el_set (m_editline, EL_BIND, "\r", "lldb-break-line", NULL); + el_set (m_editline, EL_BIND, "^p", "lldb-previous-line", NULL); + el_set (m_editline, EL_BIND, "^n", "lldb-next-line", NULL); + el_set (m_editline, EL_BIND, "^?", "lldb-delete-previous-char", NULL); + el_set (m_editline, EL_BIND, "^d", "lldb-delete-next-char", NULL); + el_set (m_editline, EL_BIND, ESCAPE "[3~", "lldb-delete-next-char", NULL); + el_set (m_editline, EL_BIND, ESCAPE "[\\^", "lldb-revert-line", NULL); + + // Editor-specific bindings + if (IsEmacs()) + { + el_set (m_editline, EL_BIND, ESCAPE "<", "lldb-buffer-start", NULL); + el_set (m_editline, EL_BIND, ESCAPE ">", "lldb-buffer-end", NULL); + el_set (m_editline, EL_BIND, ESCAPE "[A", "lldb-previous-line", NULL); + el_set (m_editline, EL_BIND, ESCAPE "[B", "lldb-next-line", NULL); + } + else + { + el_set (m_editline, EL_BIND, "^H", "lldb-delete-previous-char", NULL); + + el_set (m_editline, EL_BIND, "-a", ESCAPE "[A", "lldb-previous-line", NULL); + el_set (m_editline, EL_BIND, "-a", ESCAPE "[B", "lldb-next-line", NULL); + el_set (m_editline, EL_BIND, "-a", "x", "lldb-delete-next-char", NULL); + el_set (m_editline, EL_BIND, "-a", "^H", "lldb-delete-previous-char", NULL); + el_set (m_editline, EL_BIND, "-a", "^?", "lldb-delete-previous-char", NULL); + + // Escape is absorbed exiting edit mode, so re-register important sequences + // without the prefix + el_set (m_editline, EL_BIND, "-a", "[A", "lldb-previous-line", NULL); + el_set (m_editline, EL_BIND, "-a", "[B", "lldb-next-line", NULL); + el_set (m_editline, EL_BIND, "-a", "[\\^", "lldb-revert-line", NULL); + } + } } -FILE * -Editline::GetOutputFile () +//------------------------------------------------------------------ +// Editline public methods +//------------------------------------------------------------------ + +Editline * +Editline::InstanceFor (EditLine * editline) { - return GetFilePointer (m_editline, 1); + Editline * editor; + el_get (editline, EL_CLIENTDATA, &editor); + return editor; } -FILE * -Editline::GetErrorFile () +Editline::Editline (const char * editline_name, FILE * input_file, FILE * output_file, FILE * error_file, bool color_prompts) : + m_editor_status (EditorStatus::Complete), + m_color_prompts(color_prompts), + m_input_file (input_file), + m_output_file (output_file), + m_error_file (error_file), + m_input_connection (fileno(input_file), false) { - return GetFilePointer (m_editline, 2); + // Get a shared history instance + m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name; + m_history_sp = EditlineHistory::GetHistory (m_editor_name); } -const char * -Editline::GetPrompt() +Editline::~Editline() { - if (m_prompt_with_line_numbers && m_lines_curr_line > 0) + if (m_editline) { - StreamString strm; - strm.Printf("%3u: ", m_lines_curr_line); - m_lines_prompt = std::move(strm.GetString()); - return m_lines_prompt.c_str(); - } - else - { - return m_prompt.c_str(); + // Disable edit mode to stop the terminal from flushing all input + // during the call to el_end() since we expect to have multiple editline + // instances in this program. + el_set (m_editline, EL_EDITMODE, 0); + el_end (m_editline); + m_editline = nullptr; } + + // EditlineHistory objects are sometimes shared between multiple + // Editline instances with the same program name. So just release + // our shared pointer and if we are the last owner, it will save the + // history to the history save file automatically. + m_history_sp.reset(); } void -Editline::SetPrompt (const char *p) +Editline::SetPrompt (const char * prompt) { - if (p && p[0]) - m_prompt = p; - else - m_prompt.clear(); - size_t start_pos = 0; - size_t escape_pos; - while ((escape_pos = m_prompt.find('\033', start_pos)) != std::string::npos) - { - m_prompt.insert(escape_pos, 1, k_prompt_escape_char); - start_pos += 2; - } + m_set_prompt = prompt == nullptr ? "" : prompt; } -FILE * -Editline::GetFilePointer (::EditLine *e, int fd) +void +Editline::SetContinuationPrompt (const char * continuation_prompt) { - FILE *file_ptr = NULL; - if (e && ::el_get(e, EL_GETFP, fd, &file_ptr) == 0) - return file_ptr; - return NULL; + m_set_continuation_prompt = continuation_prompt == nullptr ? "" : continuation_prompt; } -unsigned char -Editline::CallbackEditPrevLine (::EditLine *e, int ch) +void +Editline::TerminalSizeChanged() { - Editline *editline = GetClientData (e); - if (editline->m_lines_curr_line > 1) + if (m_editline != nullptr) { - editline->m_lines_command = Command::EditPrevLine; - return CC_NEWLINE; + el_resize (m_editline); + int columns; + // Despite the man page claiming non-zero indicates success, it's actually zero + if (el_get (m_editline, EL_GETTC, "co", &columns) == 0) + { + m_terminal_width = columns; + if (m_current_line_rows != -1) + { + const LineInfoW * info = el_wline (m_editline); + int lineLength = (int)((info->lastchar - info->buffer) + GetPromptWidth()); + m_current_line_rows = (lineLength / columns) + 1; + } + } + else + { + m_terminal_width = INT_MAX; + m_current_line_rows = 1; + } } - return CC_ERROR; } -unsigned char -Editline::CallbackEditNextLine (::EditLine *e, int ch) + +const char * +Editline::GetPrompt() { - Editline *editline = GetClientData (e); - if (editline->m_lines_curr_line < editline->m_lines_max_line) - { - editline->m_lines_command = Command::EditNextLine; - return CC_NEWLINE; - } - return CC_ERROR; + return m_set_prompt.c_str(); } -unsigned char -Editline::CallbackComplete (::EditLine *e, int ch) +uint32_t +Editline::GetCurrentLine() { - Editline *editline = GetClientData (e); - if (editline) - return editline->HandleCompletion (ch); - return CC_ERROR; + return m_current_line_index; } -const char * -Editline::GetPromptCallback (::EditLine *e) +void +Editline::Hide() { - Editline *editline = GetClientData (e); - if (editline) - return editline->GetPrompt(); - return ""; + // Make sure we're at a stable location waiting for input + while (m_editor_status == EditorStatus::Editing && !m_editor_getting_char) + { + usleep(100000); + } + + // Clear the existing input + if (m_editor_status == EditorStatus::Editing) + { + MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); + fprintf(m_output_file, ANSI_CLEAR_BELOW); + } } -int -Editline::GetCharFromInputFileCallback (EditLine *e, char *c) +void +Editline::Refresh() { - Editline *editline = GetClientData (e); - if (editline && editline->m_got_eof == false) + if (m_editor_status == EditorStatus::Editing) { - FILE *f = editline->GetInputFile(); - if (f == NULL) - { - editline->m_got_eof = true; - return 0; - } - - - while (1) - { - lldb::ConnectionStatus status = eConnectionStatusSuccess; - char ch = 0; - // When we start to call el_gets() the editline library needs to - // output the prompt - editline->m_getting_char.SetValue(true, eBroadcastAlways); - const size_t n = editline->m_file.Read(&ch, 1, UINT32_MAX, status, NULL); - editline->m_getting_char.SetValue(false, eBroadcastAlways); - if (n) - { - if (ch == '\x04') - { - // Only turn a CTRL+D into a EOF if we receive the - // CTRL+D an empty line, otherwise it will forward - // delete the character at the cursor - const LineInfo *line_info = ::el_line(e); - if (line_info != NULL && - line_info->buffer == line_info->cursor && - line_info->cursor == line_info->lastchar) - { - editline->m_got_eof = true; - break; - } - } - - if (status == eConnectionStatusEndOfFile) - { - editline->m_got_eof = true; - break; - } - else - { - *c = ch; - return 1; - } - } - else - { - switch (status) - { - case eConnectionStatusInterrupted: - editline->m_interrupted = true; - *c = '\n'; - return 1; - - case eConnectionStatusSuccess: // Success - break; - - case eConnectionStatusError: // Check GetError() for details - case eConnectionStatusTimedOut: // Request timed out - case eConnectionStatusEndOfFile: // End-of-file encountered - case eConnectionStatusNoConnection: // No connection - case eConnectionStatusLostConnection: // Lost connection while connected to a valid connection - editline->m_got_eof = true; - break; - } - } - } + DisplayInput(); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); } - return 0; } -void -Editline::Hide () +bool +Editline::Interrupt() { - if (m_getting_line) + if (m_editor_status == EditorStatus::Editing) { - // If we are getting a line, we might have started to call el_gets() and - // it might be printing the prompt. Here we make sure we are actually getting - // a character. This way we know the entire prompt has been printed. - TimeValue timeout = TimeValue::Now(); - timeout.OffsetWithSeconds(1); - if (m_getting_char.WaitForValueEqualTo(true, &timeout)) - { - FILE *out_file = GetOutputFile(); - if (out_file) - { - const LineInfo *line_info = ::el_line(m_editline); - if (line_info) - ::fprintf (out_file, "\033[%uD\033[K", (uint32_t)(strlen(GetPrompt()) + line_info->cursor - line_info->buffer)); - } - } + return m_input_connection.InterruptRead(); } + return false; // Interrupt not handled as we weren't getting a line or lines } +void +Editline::SetAutoCompleteCallback (CompleteCallbackType callback, void * baton) +{ + m_completion_callback = callback; + m_completion_callback_baton = baton; +} void -Editline::Refresh() +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) { - if (m_getting_line) + 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(); + m_input_lines.insert (m_input_lines.begin(), EditLineConstString("")); + + SetCurrentLine (0); + m_in_history = false; + m_editor_status = EditorStatus::Editing; + m_editor_getting_char = false; + m_revert_cursor_index = -1; + + int count; + auto input = el_wgets (m_editline, &count); + + interrupted = m_editor_status == EditorStatus::Interrupted; + if (!interrupted) { - // If we are getting a line, we might have started to call el_gets() and - // it might be printing the prompt. Here we make sure we are actually getting - // a character. This way we know the entire prompt has been printed. - TimeValue timeout = TimeValue::Now(); - timeout.OffsetWithSeconds(1); - if (m_getting_char.WaitForValueEqualTo(true, &timeout)) + if (input == nullptr) { - ::el_set (m_editline, EL_REFRESH); + fprintf (m_output_file, "\n"); + m_editor_status = EditorStatus::EndOfInput; + } + else + { + m_history_sp->Enter (input); +#if LLDB_EDITLINE_USE_WCHAR + line = m_utf8conv.to_bytes (SplitLines (input)[0]); +#else + line = SplitLines (input)[0]; +#endif + m_editor_status = EditorStatus::Complete; } } + return m_editor_status != EditorStatus::EndOfInput; } bool -Editline::Interrupt () +Editline::GetLines (int first_line_number, StringList &lines, bool &interrupted) { - m_interrupted = true; - if (m_getting_line || m_lines_curr_line > 0) - return m_file.InterruptRead(); - return false; // Interrupt not handled as we weren't getting a line or lines + ConfigureEditor (true); + + // Print the initial input lines, then move the cursor back up to the start of input + SetBaseLineNumber (first_line_number); + m_input_lines = std::vector(); + m_input_lines.insert (m_input_lines.begin(), EditLineConstString("")); + + // Begin the line editing loop + DisplayInput(); + SetCurrentLine (0); + MoveCursor (CursorLocation::BlockEnd, CursorLocation::BlockStart); + m_editor_status = EditorStatus::Editing; + m_editor_getting_char = false; + m_in_history = false; + + m_revert_cursor_index = -1; + while (m_editor_status == EditorStatus::Editing) + { + int count; + m_current_line_rows = -1; + el_wpush (m_editline, EditLineConstString("\x1b[^")); // Revert to the existing line content + el_wgets (m_editline, &count); + } + + interrupted = m_editor_status == EditorStatus::Interrupted; + if (!interrupted) + { + // Save the completed entry in history before returning + m_history_sp->Enter (CombineLines (m_input_lines).c_str()); + + lines = GetInputAsStringList(); + } + return m_editor_status != EditorStatus::EndOfInput; } diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp index 50513af2dc14..c3c77835ce86 100644 --- a/source/Host/common/File.cpp +++ b/source/Host/common/File.cpp @@ -896,7 +896,7 @@ File::CalculateInteractiveAndTerminal () { m_is_interactive = eLazyBoolNo; m_is_real_terminal = eLazyBoolNo; -#ifdef _WIN32 +#if (defined(_WIN32) || defined(__ANDROID_NDK__)) if (_isatty(fd)) { m_is_interactive = eLazyBoolYes; diff --git a/source/Host/common/FileSpec.cpp b/source/Host/common/FileSpec.cpp index 8c4014c074f5..0af0556d30c9 100644 --- a/source/Host/common/FileSpec.cpp +++ b/source/Host/common/FileSpec.cpp @@ -56,7 +56,8 @@ GetFileStats (const FileSpec *file_spec, struct stat *stats_ptr) } // Resolves the username part of a path of the form ~user/other/directories, and -// writes the result into dst_path. +// writes the result into dst_path. This will also resolve "~" to the current user. +// If you want to complete "~" to the list of users, pass it to ResolvePartialUsername. void FileSpec::ResolveUsername (llvm::SmallVectorImpl &path) { @@ -66,9 +67,9 @@ FileSpec::ResolveUsername (llvm::SmallVectorImpl &path) llvm::StringRef path_str(path.data()); size_t slash_pos = path_str.find_first_of("/", 1); - if (slash_pos == 1) + if (slash_pos == 1 || path.size() == 1) { - // A path of the form ~/ resolves to the current user's home dir + // A path of ~/ resolves to the current user's home dir llvm::SmallString<64> home_dir; if (!llvm::sys::path::home_directory(home_dir)) return; @@ -166,10 +167,10 @@ FileSpec::Resolve (llvm::SmallVectorImpl &path) llvm::sys::fs::make_absolute(path); } -FileSpec::FileSpec() - : m_directory() - , m_filename() - , m_syntax(FileSystem::GetNativePathSyntax()) +FileSpec::FileSpec() : + m_directory(), + m_filename(), + m_syntax(FileSystem::GetNativePathSyntax()) { } @@ -180,7 +181,8 @@ FileSpec::FileSpec() FileSpec::FileSpec(const char *pathname, bool resolve_path, PathSyntax syntax) : m_directory(), m_filename(), - m_is_resolved(false) + m_is_resolved(false), + m_syntax(syntax) { if (pathname && pathname[0]) SetFile(pathname, resolve_path, syntax); @@ -266,14 +268,18 @@ FileSpec::SetFile (const char *pathname, bool resolve, PathSyntax syntax) return; llvm::SmallString<64> normalized(pathname); - Normalize(normalized, syntax); if (resolve) { FileSpec::Resolve (normalized); m_is_resolved = true; } - + + // Only normalize after resolving the path. Resolution will modify the path + // string, potentially adding wrong kinds of slashes to the path, that need + // to be re-normalized. + Normalize(normalized, syntax); + llvm::StringRef resolve_path_ref(normalized.c_str()); llvm::StringRef filename_ref = llvm::sys::path::filename(resolve_path_ref); if (!filename_ref.empty()) @@ -446,15 +452,129 @@ FileSpec::Compare(const FileSpec& a, const FileSpec& b, bool full) } bool -FileSpec::Equal (const FileSpec& a, const FileSpec& b, bool full) +FileSpec::Equal (const FileSpec& a, const FileSpec& b, bool full, bool remove_backups) { if (!full && (a.GetDirectory().IsEmpty() || b.GetDirectory().IsEmpty())) return a.m_filename == b.m_filename; - else + else if (remove_backups == false) return a == b; + else + { + if (a.m_filename != b.m_filename) + return false; + if (a.m_directory == b.m_directory) + return true; + ConstString a_without_dots; + ConstString b_without_dots; + + RemoveBackupDots (a.m_directory, a_without_dots); + RemoveBackupDots (b.m_directory, b_without_dots); + return a_without_dots == b_without_dots; + } } +void +FileSpec::RemoveBackupDots (const ConstString &input_const_str, ConstString &result_const_str) +{ + const char *input = input_const_str.GetCString(); + result_const_str.Clear(); + if (!input || input[0] == '\0') + return; + + const char win_sep = '\\'; + const char unix_sep = '/'; + char found_sep; + const char *win_backup = "\\.."; + const char *unix_backup = "/.."; + + bool is_win = false; + + // Determine the platform for the path (win or unix): + + if (input[0] == win_sep) + is_win = true; + else if (input[0] == unix_sep) + is_win = false; + else if (input[1] == ':') + is_win = true; + else if (strchr(input, unix_sep) != nullptr) + is_win = false; + else if (strchr(input, win_sep) != nullptr) + is_win = true; + else + { + // No separators at all, no reason to do any work here. + result_const_str = input_const_str; + return; + } + + llvm::StringRef backup_sep; + if (is_win) + { + found_sep = win_sep; + backup_sep = win_backup; + } + else + { + found_sep = unix_sep; + backup_sep = unix_backup; + } + + llvm::StringRef input_ref(input); + llvm::StringRef curpos(input); + + bool had_dots = false; + std::string result; + + while (1) + { + // Start of loop + llvm::StringRef before_sep; + std::pair around_sep = curpos.split(backup_sep); + + before_sep = around_sep.first; + curpos = around_sep.second; + + if (curpos.empty()) + { + if (had_dots) + { + if (!before_sep.empty()) + { + result.append(before_sep.data(), before_sep.size()); + } + } + break; + } + had_dots = true; + unsigned num_backups = 1; + while (curpos.startswith(backup_sep)) + { + num_backups++; + curpos = curpos.slice(backup_sep.size(), curpos.size()); + } + + size_t end_pos = before_sep.size(); + while (num_backups-- > 0) + { + end_pos = before_sep.rfind(found_sep, end_pos); + if (end_pos == llvm::StringRef::npos) + { + result_const_str = input_const_str; + return; + } + } + result.append(before_sep.data(), end_pos); + } + + if (had_dots) + result_const_str.SetCString(result.c_str()); + else + result_const_str = input_const_str; + + return; +} //------------------------------------------------------------------ // Dump the object to the supplied stream. If the object contains @@ -502,7 +622,10 @@ FileSpec::ResolveExecutableLocation () if (file_cstr) { const std::string file_str (file_cstr); - std::string path = llvm::sys::FindProgramByName (file_str); + llvm::ErrorOr error_or_path = llvm::sys::findProgramByName (file_str); + if (!error_or_path) + return false; + std::string path = error_or_path.get(); llvm::StringRef dir_ref = llvm::sys::path::parent_path(path); if (!dir_ref.empty()) { @@ -946,6 +1069,8 @@ FileSpec::EnumerateDirectory lldb_utility::CleanUp dir_path_dir(opendir(dir_path), NULL, closedir); if (dir_path_dir.is_valid()) { + char dir_path_last_char = dir_path[strlen(dir_path) - 1]; + long path_max = fpathconf (dirfd (dir_path_dir.get()), _PC_NAME_MAX); #if defined (__APPLE_) && defined (__DARWIN_MAXPATHLEN) if (path_max < __DARWIN_MAXPATHLEN) @@ -990,7 +1115,14 @@ FileSpec::EnumerateDirectory if (call_callback) { char child_path[PATH_MAX]; - const int child_path_len = ::snprintf (child_path, sizeof(child_path), "%s/%s", dir_path, dp->d_name); + + // Don't make paths with "/foo//bar", that just confuses everybody. + int child_path_len; + if (dir_path_last_char == '/') + child_path_len = ::snprintf (child_path, sizeof(child_path), "%s%s", dir_path, dp->d_name); + else + child_path_len = ::snprintf (child_path, sizeof(child_path), "%s/%s", dir_path, dp->d_name); + if (child_path_len < (int)(sizeof(child_path) - 1)) { // Don't resolve the file type or path @@ -1208,18 +1340,31 @@ FileSpec::IsSourceImplementationFile () const bool FileSpec::IsRelativeToCurrentWorkingDirectory () const { - const char *directory = m_directory.GetCString(); - if (directory && directory[0]) + const char *dir = m_directory.GetCString(); + llvm::StringRef directory(dir ? dir : ""); + + if (directory.size() > 0) { - // If the path doesn't start with '/' or '~', return true - switch (directory[0]) + if (m_syntax == ePathSyntaxWindows) { - case '/': - case '~': - return false; - default: + if (directory.size() >= 2 && directory[1] == ':') + return false; + if (directory[0] == '/') + return false; return true; } + else + { + // If the path doesn't start with '/' or '~', return true + switch (directory[0]) + { + case '/': + case '~': + return false; + default: + return true; + } + } } else if (m_filename) { diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp index 00c2fa37b383..c8daa175d1bd 100644 --- a/source/Host/common/Host.cpp +++ b/source/Host/common/Host.cpp @@ -14,11 +14,7 @@ #include #include #include -#ifdef _WIN32 -#include "lldb/Host/windows/windows.h" -#include -#include -#else +#ifndef _WIN32 #include #include #include @@ -27,11 +23,6 @@ #include #endif -#if !defined (__GNU__) && !defined (_WIN32) -// Does not exist under GNU/HURD or Windows -#include -#endif - #if defined (__APPLE__) #include #include @@ -39,7 +30,9 @@ #endif #if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__) || defined(__NetBSD__) +#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) #include +#endif #include #include #endif @@ -51,33 +44,30 @@ // C++ includes #include +#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/ConstString.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Core/ThreadSafeSTLMap.h" -#include "lldb/Host/Config.h" -#include "lldb/Host/Endian.h" #include "lldb/Host/FileSpec.h" -#include "lldb/Host/FileSystem.h" -#include "lldb/Host/Mutex.h" +#include "lldb/Host/HostProcess.h" +#include "lldb/Host/MonitoringProcessLauncher.h" +#include "lldb/Host/ProcessLauncher.h" +#include "lldb/Host/ThreadLauncher.h" #include "lldb/lldb-private-forward.h" #include "lldb/Target/FileAction.h" -#include "lldb/Target/Process.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/TargetList.h" #include "lldb/Utility/CleanUp.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" +#if defined(_WIN32) +#include "lldb/Host/windows/ProcessLauncherWindows.h" +#else +#include "lldb/Host/posix/ProcessLauncherPosix.h" +#endif #if defined (__APPLE__) #ifndef _POSIX_SPAWN_DISABLE_ASLR @@ -95,13 +85,6 @@ extern "C" using namespace lldb; using namespace lldb_private; -// Define maximum thread name length -#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__NetBSD__) -uint32_t const Host::MAX_THREAD_NAME_LENGTH = 16; -#else -uint32_t const Host::MAX_THREAD_NAME_LENGTH = std::numeric_limits::max (); -#endif - #if !defined (__APPLE__) && !defined (_WIN32) struct MonitorInfo { @@ -114,16 +97,9 @@ struct MonitorInfo static thread_result_t MonitorChildProcessThreadFunction (void *arg); -lldb::thread_t -Host::StartMonitoringChildProcess -( - Host::MonitorChildProcessCallback callback, - void *callback_baton, - lldb::pid_t pid, - bool monitor_signals -) +HostThread +Host::StartMonitoringChildProcess(Host::MonitorChildProcessCallback callback, void *callback_baton, lldb::pid_t pid, bool monitor_signals) { - lldb::thread_t thread = LLDB_INVALID_HOST_THREAD; MonitorInfo * info_ptr = new MonitorInfo(); info_ptr->pid = pid; @@ -132,26 +108,11 @@ Host::StartMonitoringChildProcess info_ptr->monitor_signals = monitor_signals; char thread_name[256]; - - if (Host::MAX_THREAD_NAME_LENGTH <= 16) - { - // On some platforms, the thread name is limited to 16 characters. We need to - // abbreviate there or the pid info would get truncated. - ::snprintf (thread_name, sizeof(thread_name), "wait4(%" PRIu64 ")", pid); - } - else - { - ::snprintf (thread_name, sizeof(thread_name), "", pid); - } - - thread = ThreadCreate (thread_name, - MonitorChildProcessThreadFunction, - info_ptr, - NULL); - - return thread; + ::snprintf(thread_name, sizeof(thread_name), "", pid); + return ThreadLauncher::LaunchThread(thread_name, MonitorChildProcessThreadFunction, info_ptr, NULL); } +#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) //------------------------------------------------------------------ // Scoped class that will disable thread canceling when it is // constructed, and exception safely restore the previous value it @@ -166,7 +127,6 @@ public: int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &m_old_state); if (err != 0) m_old_state = -1; - } ~ScopedPThreadCancelDisabler() @@ -179,6 +139,7 @@ public: private: int m_old_state; // Save the old cancelability state. }; +#endif // __ANDROID_NDK__ static thread_result_t MonitorChildProcessThreadFunction (void *arg) @@ -212,11 +173,14 @@ MonitorChildProcessThreadFunction (void *arg) log->Printf("%s ::wait_pid (pid = %" PRIi32 ", &status, options = %i)...", function, pid, options); // Wait for all child processes +#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) ::pthread_testcancel (); +#endif // Get signals from all children with same process group of pid const ::pid_t wait_pid = ::waitpid (pid, &status, options); +#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) ::pthread_testcancel (); - +#endif if (wait_pid == -1) { if (errno == EINTR) @@ -261,7 +225,9 @@ MonitorChildProcessThreadFunction (void *arg) // Scope for pthread_cancel_disabler { +#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) ScopedPThreadCancelDisabler pthread_cancel_disabler; +#endif log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); if (log) @@ -349,6 +315,8 @@ Host::GetCurrentThreadID() return thread_self; #elif defined(__FreeBSD__) return lldb::tid_t(pthread_getthreadid_np()); +#elif defined(__ANDROID_NDK__) + return lldb::tid_t(gettid()); #elif defined(__linux__) return lldb::tid_t(syscall(SYS_gettid)); #else @@ -428,11 +396,6 @@ Host::WillTerminate () #if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined (__linux__) // see macosx/Host.mm -void -Host::ThreadCreated (const char *thread_name) -{ -} - void Host::Backtrace (Stream &strm, uint32_t max_frames) { @@ -448,101 +411,8 @@ Host::GetEnvironment (StringList &env) #endif // #if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined (__linux__) -struct HostThreadCreateInfo -{ - std::string thread_name; - thread_func_t thread_fptr; - thread_arg_t thread_arg; - - HostThreadCreateInfo (const char *name, thread_func_t fptr, thread_arg_t arg) : - thread_name (name ? name : ""), - thread_fptr (fptr), - thread_arg (arg) - { - } -}; - -static thread_result_t -#ifdef _WIN32 -__stdcall -#endif -ThreadCreateTrampoline (thread_arg_t arg) -{ - HostThreadCreateInfo *info = (HostThreadCreateInfo *)arg; - Host::ThreadCreated (info->thread_name.c_str()); - thread_func_t thread_fptr = info->thread_fptr; - thread_arg_t thread_arg = info->thread_arg; - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("thread created"); - - delete info; - return thread_fptr (thread_arg); -} - -lldb::thread_t -Host::ThreadCreate -( - const char *thread_name, - thread_func_t thread_fptr, - thread_arg_t thread_arg, - Error *error -) -{ - lldb::thread_t thread = LLDB_INVALID_HOST_THREAD; - - // Host::ThreadCreateTrampoline will delete this pointer for us. - HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo (thread_name, thread_fptr, thread_arg); - -#ifdef _WIN32 - thread = ::_beginthreadex(0, 0, ThreadCreateTrampoline, info_ptr, 0, NULL); - int err = thread <= 0 ? GetLastError() : 0; -#else - int err = ::pthread_create (&thread, NULL, ThreadCreateTrampoline, info_ptr); -#endif - if (err == 0) - { - if (error) - error->Clear(); - return thread; - } - - if (error) - error->SetError (err, eErrorTypePOSIX); - - return LLDB_INVALID_HOST_THREAD; -} - #ifndef _WIN32 -bool -Host::ThreadCancel (lldb::thread_t thread, Error *error) -{ - int err = ::pthread_cancel (thread); - if (error) - error->SetError(err, eErrorTypePOSIX); - return err == 0; -} - -bool -Host::ThreadDetach (lldb::thread_t thread, Error *error) -{ - int err = ::pthread_detach (thread); - if (error) - error->SetError(err, eErrorTypePOSIX); - return err == 0; -} - -bool -Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Error *error) -{ - int err = ::pthread_join (thread, thread_result_ptr); - if (error) - error->SetError(err, eErrorTypePOSIX); - return err == 0; -} - lldb::thread_key_t Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) { @@ -563,99 +433,6 @@ Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) ::pthread_setspecific (key, value); } -bool -Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name) -{ -#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 - lldb::pid_t curr_pid = Host::GetCurrentProcessID(); - lldb::tid_t curr_tid = Host::GetCurrentThreadID(); - if (pid == LLDB_INVALID_PROCESS_ID) - pid = curr_pid; - - if (tid == LLDB_INVALID_THREAD_ID) - tid = curr_tid; - - // Set the pthread name if possible - if (pid == curr_pid && tid == curr_tid) - { - if (::pthread_setname_np (name) == 0) - return true; - } - return false; -#elif defined (__FreeBSD__) - lldb::pid_t curr_pid = Host::GetCurrentProcessID(); - lldb::tid_t curr_tid = Host::GetCurrentThreadID(); - if (pid == LLDB_INVALID_PROCESS_ID) - pid = curr_pid; - - if (tid == LLDB_INVALID_THREAD_ID) - tid = curr_tid; - - // Set the pthread name if possible - if (pid == curr_pid && tid == curr_tid) - { - ::pthread_set_name_np (::pthread_self(), name); - return true; - } - return false; -#elif defined (__linux__) || defined (__GLIBC__) - void *fn = dlsym (RTLD_DEFAULT, "pthread_setname_np"); - if (fn) - { - lldb::pid_t curr_pid = Host::GetCurrentProcessID(); - lldb::tid_t curr_tid = Host::GetCurrentThreadID(); - if (pid == LLDB_INVALID_PROCESS_ID) - pid = curr_pid; - - if (tid == LLDB_INVALID_THREAD_ID) - tid = curr_tid; - - if (pid == curr_pid && tid == curr_tid) - { - int (*pthread_setname_np_func)(pthread_t thread, const char *name); - *reinterpret_cast (&pthread_setname_np_func) = fn; - - if (pthread_setname_np_func (::pthread_self(), name) == 0) - return true; - } - } - return false; -#else - return false; -#endif -} - -bool -Host::SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid, - const char *thread_name, size_t len) -{ - std::unique_ptr namebuf(new char[len+1]); - - // Thread names are coming in like '' and - // ''. So just chopping the end of the string - // off leads to a lot of similar named threads. Go through the thread name - // and search for the last dot and use that. - const char *lastdot = ::strrchr (thread_name, '.'); - - if (lastdot && lastdot != thread_name) - thread_name = lastdot + 1; - ::strncpy (namebuf.get(), thread_name, len); - namebuf[len] = 0; - - int namebuflen = strlen(namebuf.get()); - if (namebuflen > 0) - { - if (namebuf[namebuflen - 1] == '(' || namebuf[namebuflen - 1] == '>') - { - // Trim off trailing '(' and '>' characters for a bit more cleanup. - namebuflen--; - namebuf[namebuflen] = 0; - } - return Host::SetThreadName (pid, tid, namebuf.get()); - } - return false; -} - #endif #if !defined (__APPLE__) // see Host.mm @@ -680,12 +457,16 @@ FileSpec Host::GetModuleFileSpecForHostAddress (const void *host_addr) { FileSpec module_filespec; +#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) Dl_info info; if (::dladdr (host_addr, &info)) { if (info.dli_fname) module_filespec.SetFile(info.dli_fname, true); } +#else + assert(false && "dladdr() not supported on Android"); +#endif return module_filespec; } @@ -699,28 +480,6 @@ Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach) } #endif -lldb::TargetSP -Host::GetDummyTarget (lldb_private::Debugger &debugger) -{ - static TargetSP g_dummy_target_sp; - - // FIXME: Maybe the dummy target should be per-Debugger - if (!g_dummy_target_sp || !g_dummy_target_sp->IsValid()) - { - ArchSpec arch(Target::GetDefaultArchitecture()); - if (!arch.IsValid()) - arch = HostInfo::GetArchitecture(); - Error err = debugger.GetTargetList().CreateTarget(debugger, - NULL, - arch.GetTriple().getTriple().c_str(), - false, - NULL, - g_dummy_target_sp); - } - - return g_dummy_target_sp; -} - struct ShellInfo { ShellInfo () : @@ -770,14 +529,15 @@ Host::RunShellCommand (const char *command, int *signo_ptr, std::string *command_output_ptr, uint32_t timeout_sec, - const char *shell) + bool run_in_default_shell) { Error error; ProcessLaunchInfo launch_info; - if (shell && shell[0]) + launch_info.SetArchitecture(HostInfo::GetArchitecture()); + if (run_in_default_shell) { // Run the command in a shell - launch_info.SetShell(shell); + launch_info.SetShell(HostInfo::GetDefaultShell()); launch_info.GetArguments().AppendArgument(command); const bool localhost = true; const bool will_debug = false; @@ -798,9 +558,8 @@ Host::RunShellCommand (const char *command, if (working_dir) launch_info.SetWorkingDirectory(working_dir); - char output_file_path_buffer[PATH_MAX]; - const char *output_file_path = NULL; - + llvm::SmallString output_file_path; + if (command_output_ptr) { // Create a temporary file to get the stdout/stderr and redirect the @@ -809,21 +568,19 @@ Host::RunShellCommand (const char *command, FileSpec tmpdir_file_spec; if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) { - tmpdir_file_spec.AppendPathComponent("lldb-shell-output.XXXXXX"); - strncpy(output_file_path_buffer, tmpdir_file_spec.GetPath().c_str(), sizeof(output_file_path_buffer)); + tmpdir_file_spec.AppendPathComponent("lldb-shell-output.%%%%%%"); + llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(), output_file_path); } else { - strncpy(output_file_path_buffer, "/tmp/lldb-shell-output.XXXXXX", sizeof(output_file_path_buffer)); + llvm::sys::fs::createTemporaryFile("lldb-shell-output.%%%%%%", "", output_file_path); } - - output_file_path = ::mktemp(output_file_path_buffer); } launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); - if (output_file_path) + if (!output_file_path.empty()) { - launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_path, false, true); + launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_path.c_str(), false, true); launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO); } else @@ -882,7 +639,7 @@ Host::RunShellCommand (const char *command, if (command_output_ptr) { command_output_ptr->clear(); - FileSpec file_spec(output_file_path, File::eOpenOptionRead); + FileSpec file_spec(output_file_path.c_str(), File::eOpenOptionRead); uint64_t file_size = file_spec.GetByteSize(); if (file_size > 0) { @@ -901,8 +658,9 @@ Host::RunShellCommand (const char *command, shell_info->can_delete.SetValue(true, eBroadcastAlways); } - if (output_file_path) - ::unlink (output_file_path); + FileSpec output_file_spec(output_file_path.c_str(), false); + if (FileSystem::GetFileExists(output_file_spec)) + FileSystem::Unlink(output_file_path.c_str()); // Handshake with the monitor thread, or just let it know in advance that // it can delete "shell_info" in case we timed out and were not able to kill // the process... @@ -914,13 +672,13 @@ Host::RunShellCommand (const char *command, // systems #if defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined(__NetBSD__) - // this method needs to be visible to macosx/Host.cpp and // common/Host.cpp. short -Host::GetPosixspawnFlags (ProcessLaunchInfo &launch_info) +Host::GetPosixspawnFlags(const ProcessLaunchInfo &launch_info) { +#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; #if defined (__APPLE__) @@ -963,12 +721,17 @@ Host::GetPosixspawnFlags (ProcessLaunchInfo &launch_info) #endif #endif // #if defined (__APPLE__) return flags; +#else + assert(false && "Host::GetPosixspawnFlags() not supported on Android"); + return 0; +#endif } Error -Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid) +Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &launch_info, lldb::pid_t &pid) { Error error; +#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); posix_spawnattr_t attr; @@ -1086,6 +849,7 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i #endif } + ::pid_t result_pid = LLDB_INVALID_PROCESS_ID; const size_t num_file_actions = launch_info.GetNumFileActions (); if (num_file_actions > 0) { @@ -1110,21 +874,13 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i } } - error.SetError (::posix_spawnp (&pid, - exe_path, - &file_actions, - &attr, - argv, - envp), - eErrorTypePOSIX); + error.SetError(::posix_spawnp(&result_pid, exe_path, &file_actions, &attr, argv, envp), eErrorTypePOSIX); if (error.Fail() || log) { - error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", - pid, exe_path, static_cast(&file_actions), - static_cast(&attr), - reinterpret_cast(argv), - reinterpret_cast(envp)); + error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", result_pid, + exe_path, static_cast(&file_actions), static_cast(&attr), reinterpret_cast(argv), + reinterpret_cast(envp)); if (log) { for (int ii=0; argv[ii]; ++ii) @@ -1135,20 +891,13 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i } else { - error.SetError (::posix_spawnp (&pid, - exe_path, - NULL, - &attr, - argv, - envp), - eErrorTypePOSIX); + error.SetError(::posix_spawnp(&result_pid, exe_path, NULL, &attr, argv, envp), eErrorTypePOSIX); if (error.Fail() || log) { error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )", - pid, exe_path, static_cast(&attr), - reinterpret_cast(argv), - reinterpret_cast(envp)); + result_pid, exe_path, static_cast(&attr), reinterpret_cast(argv), + reinterpret_cast(envp)); if (log) { for (int ii=0; argv[ii]; ++ii) @@ -1156,6 +905,7 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i } } } + pid = result_pid; if (working_dir) { @@ -1171,6 +921,9 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i } #endif } +#else + error.SetErrorString("Host::LaunchProcessPosixSpawn() not supported on Android"); +#endif return error; } @@ -1178,6 +931,7 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i bool Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log *log, Error &error) { +#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) if (info == NULL) return false; @@ -1240,97 +994,40 @@ Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log * break; } return error.Success(); +#else + error.SetErrorString("Host::AddPosixSpawnFileAction() not supported on Android"); + return false; +#endif } - #endif // LaunchProcedssPosixSpawn: Apple, Linux, FreeBSD and other GLIBC systems - -#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__) || defined(__NetBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__) || defined(__NetBSD__) || defined(_WIN32) // The functions below implement process launching via posix_spawn() for Linux, // FreeBSD and NetBSD. Error Host::LaunchProcess (ProcessLaunchInfo &launch_info) { - Error error; - char exe_path[PATH_MAX]; - - PlatformSP host_platform_sp (Platform::GetDefaultPlatform ()); - - const ArchSpec &arch_spec = launch_info.GetArchitecture(); - - FileSpec exe_spec(launch_info.GetExecutableFile()); - - FileSpec::FileType file_type = exe_spec.GetFileType(); - if (file_type != FileSpec::eFileTypeRegular) - { - lldb::ModuleSP exe_module_sp; - error = host_platform_sp->ResolveExecutable (exe_spec, - arch_spec, - exe_module_sp, - NULL); - - if (error.Fail()) - return error; - - if (exe_module_sp) - exe_spec = exe_module_sp->GetFileSpec(); - } - - if (exe_spec.Exists()) - { - exe_spec.GetPath (exe_path, sizeof(exe_path)); - } - else - { - launch_info.GetExecutableFile().GetPath (exe_path, sizeof(exe_path)); - error.SetErrorStringWithFormat ("executable doesn't exist: '%s'", exe_path); - return error; - } - - assert(!launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY)); - - ::pid_t pid = LLDB_INVALID_PROCESS_ID; - - error = LaunchProcessPosixSpawn(exe_path, launch_info, pid); + std::unique_ptr delegate_launcher; +#if defined(_WIN32) + delegate_launcher.reset(new ProcessLauncherWindows()); +#else + delegate_launcher.reset(new ProcessLauncherPosix()); +#endif + MonitoringProcessLauncher launcher(std::move(delegate_launcher)); - if (pid != LLDB_INVALID_PROCESS_ID) - { - // If all went well, then set the process ID into the launch info - launch_info.SetProcessID(pid); + Error error; + HostProcess process = launcher.LaunchProcess(launch_info, error); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); + // TODO(zturner): It would be better if the entire HostProcess were returned instead of writing + // it into this structure. + launch_info.SetProcessID(process.GetProcessId()); - // Make sure we reap any processes we spawn or we will have zombies. - if (!launch_info.MonitorProcess()) - { - const bool monitor_signals = false; - StartMonitoringChildProcess (Process::SetProcessExitStatus, - NULL, - pid, - monitor_signals); - if (log) - log->PutCString ("monitored child process with default Process::SetProcessExitStatus."); - } - else - { - if (log) - log->PutCString ("monitored child process with user-specified process monitor."); - } - } - else - { - // Invalid process ID, something didn't go well - if (error.Success()) - error.SetErrorString ("process launch failed for unknown reasons"); - } return error; } - #endif // defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) #ifndef _WIN32 - void Host::Kill(lldb::pid_t pid, int signo) { diff --git a/source/Host/common/HostInfoBase.cpp b/source/Host/common/HostInfoBase.cpp index 4eb43bfaf6ff..d65b79698384 100644 --- a/source/Host/common/HostInfoBase.cpp +++ b/source/Host/common/HostInfoBase.cpp @@ -18,7 +18,9 @@ #include "lldb/Host/HostInfoBase.h" #include "llvm/ADT/Triple.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/Host.h" +#include "llvm/Support/raw_ostream.h" #include @@ -54,6 +56,7 @@ struct HostInfoBaseFields FileSpec m_lldb_support_exe_dir; FileSpec m_lldb_headers_dir; FileSpec m_lldb_python_dir; + FileSpec m_lldb_clang_resource_dir; FileSpec m_lldb_system_plugin_dir; FileSpec m_lldb_user_plugin_dir; FileSpec m_lldb_tmp_dir; @@ -94,6 +97,12 @@ HostInfoBase::GetNumberCPUS() return g_fields->m_number_cpus; } +uint32_t +HostInfoBase::GetMaxThreadNameLength() +{ + return 0; +} + llvm::StringRef HostInfoBase::GetVendorString() { @@ -190,6 +199,11 @@ HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) if (log) log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str()); break; + case lldb::ePathTypeClangDir: + COMPUTE_LLDB_PATH(ComputeClangDirectory, g_fields->m_lldb_clang_resource_dir) + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str()); + break; case lldb::ePathTypeLLDBSystemPlugins: COMPUTE_LLDB_PATH(ComputeSystemPluginsDirectory, g_fields->m_lldb_system_plugin_dir) if (log) @@ -252,19 +266,23 @@ HostInfoBase::ComputeTempFileDirectory(FileSpec &file_spec) if (!tmpdir_cstr) return false; - StreamString pid_tmpdir; - pid_tmpdir.Printf("%s/lldb", tmpdir_cstr); - if (!FileSystem::MakeDirectory(pid_tmpdir.GetString().c_str(), eFilePermissionsDirectoryDefault).Success()) + FileSpec temp_file_spec(tmpdir_cstr, false); + temp_file_spec.AppendPathComponent("lldb"); + if (!FileSystem::MakeDirectory(temp_file_spec.GetPath().c_str(), eFilePermissionsDirectoryDefault).Success()) return false; - pid_tmpdir.Printf("/%" PRIu64, Host::GetCurrentProcessID()); - if (!FileSystem::MakeDirectory(pid_tmpdir.GetString().c_str(), eFilePermissionsDirectoryDefault).Success()) + std::string pid_str; + llvm::raw_string_ostream pid_stream(pid_str); + pid_stream << Host::GetCurrentProcessID(); + temp_file_spec.AppendPathComponent(pid_stream.str().c_str()); + std::string final_path = temp_file_spec.GetPath(); + if (!FileSystem::MakeDirectory(final_path.c_str(), eFilePermissionsDirectoryDefault).Success()) return false; // Make an atexit handler to clean up the process specify LLDB temp dir // and all of its contents. ::atexit(CleanupProcessSpecificLLDBTempDir); - file_spec.GetDirectory().SetCStringWithLength(pid_tmpdir.GetString().c_str(), pid_tmpdir.GetString().size()); + file_spec.GetDirectory().SetCStringWithLength(final_path.c_str(), final_path.size()); return true; } @@ -282,6 +300,12 @@ HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) return false; } +bool +HostInfoBase::ComputeClangDirectory(FileSpec &file_spec) +{ + return false; +} + bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) { diff --git a/source/Host/common/HostNativeThreadBase.cpp b/source/Host/common/HostNativeThreadBase.cpp new file mode 100644 index 000000000000..9fea54d1e3fa --- /dev/null +++ b/source/Host/common/HostNativeThreadBase.cpp @@ -0,0 +1,82 @@ +//===-- HostNativeThreadBase.cpp --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Log.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Host/HostNativeThreadBase.h" +#include "lldb/Host/ThisThread.h" +#include "lldb/Host/ThreadLauncher.h" +#include "llvm/ADT/StringExtras.h" + +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) +{ +} + +lldb::thread_t +HostNativeThreadBase::GetSystemHandle() const +{ + return m_thread; +} + +lldb::thread_result_t +HostNativeThreadBase::GetResult() const +{ + return m_result; +} + +bool +HostNativeThreadBase::IsJoinable() const +{ + return m_thread != LLDB_INVALID_HOST_THREAD; +} + +void +HostNativeThreadBase::Reset() +{ + m_thread = LLDB_INVALID_HOST_THREAD; + m_result = 0; +} + +lldb::thread_t +HostNativeThreadBase::Release() +{ + lldb::thread_t result = m_thread; + m_thread = LLDB_INVALID_HOST_THREAD; + m_result = 0; + + return result; +} + +lldb::thread_result_t +HostNativeThreadBase::ThreadCreateTrampoline(lldb::thread_arg_t arg) +{ + ThreadLauncher::HostThreadCreateInfo *info = (ThreadLauncher::HostThreadCreateInfo *)arg; + ThisThread::SetName(info->thread_name.c_str(), HostInfo::GetMaxThreadNameLength()); + + thread_func_t thread_fptr = info->thread_fptr; + thread_arg_t thread_arg = info->thread_arg; + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + if (log) + log->Printf("thread created"); + + delete info; + return thread_fptr(thread_arg); +} diff --git a/source/Host/common/HostProcess.cpp b/source/Host/common/HostProcess.cpp new file mode 100644 index 000000000000..58a214693a52 --- /dev/null +++ b/source/Host/common/HostProcess.cpp @@ -0,0 +1,65 @@ +//===-- HostProcess.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/HostNativeProcess.h" +#include "lldb/Host/HostProcess.h" +#include "lldb/Host/HostThread.h" + +using namespace lldb; +using namespace lldb_private; + +HostProcess::HostProcess() + : m_native_process(new HostNativeProcess) +{ +} + +HostProcess::HostProcess(lldb::process_t process) + : m_native_process(new HostNativeProcess(process)) +{ +} + +HostProcess::~HostProcess() +{ +} + +Error HostProcess::Terminate() +{ + return m_native_process->Terminate(); +} + +Error HostProcess::GetMainModule(FileSpec &file_spec) const +{ + return m_native_process->GetMainModule(file_spec); +} + +lldb::pid_t HostProcess::GetProcessId() const +{ + return m_native_process->GetProcessId(); +} + +bool HostProcess::IsRunning() const +{ + return m_native_process->IsRunning(); +} + +HostThread +HostProcess::StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals) +{ + return m_native_process->StartMonitoring(callback, callback_baton, monitor_signals); +} + +HostNativeProcessBase &HostProcess::GetNativeProcess() +{ + return *m_native_process; +} + +const HostNativeProcessBase &HostProcess::GetNativeProcess() const +{ + return *m_native_process; +} diff --git a/source/Host/common/HostThread.cpp b/source/Host/common/HostThread.cpp new file mode 100644 index 000000000000..7757477126c4 --- /dev/null +++ b/source/Host/common/HostThread.cpp @@ -0,0 +1,78 @@ +//===-- HostThread.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/HostNativeThread.h" +#include "lldb/Host/HostThread.h" + +using namespace lldb; +using namespace lldb_private; + +HostThread::HostThread() + : m_native_thread(new HostNativeThread) +{ +} + +HostThread::HostThread(lldb::thread_t thread) + : m_native_thread(new HostNativeThread(thread)) +{ +} + +Error +HostThread::Join(lldb::thread_result_t *result) +{ + return m_native_thread->Join(result); +} + +Error +HostThread::Cancel() +{ + return m_native_thread->Cancel(); +} + +void +HostThread::Reset() +{ + return m_native_thread->Reset(); +} + +lldb::thread_t +HostThread::Release() +{ + return m_native_thread->Release(); +} + +bool +HostThread::IsJoinable() const +{ + return m_native_thread->IsJoinable(); +} + +HostNativeThread & +HostThread::GetNativeThread() +{ + return static_cast(*m_native_thread); +} + +const HostNativeThread & +HostThread::GetNativeThread() const +{ + return static_cast(*m_native_thread); +} + +lldb::thread_result_t +HostThread::GetResult() const +{ + return m_native_thread->GetResult(); +} + +bool +HostThread::EqualsThread(lldb::thread_t thread) const +{ + return m_native_thread->GetSystemHandle() == thread; +} diff --git a/source/Host/common/MonitoringProcessLauncher.cpp b/source/Host/common/MonitoringProcessLauncher.cpp new file mode 100644 index 000000000000..0fad44a9ec08 --- /dev/null +++ b/source/Host/common/MonitoringProcessLauncher.cpp @@ -0,0 +1,102 @@ +//===-- ProcessLauncherWindows.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Host/HostProcess.h" +#include "lldb/Host/MonitoringProcessLauncher.h" +#include "lldb/Target/Platform.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/ProcessLaunchInfo.h" + +using namespace lldb; +using namespace lldb_private; + +MonitoringProcessLauncher::MonitoringProcessLauncher(std::unique_ptr delegate_launcher) + : m_delegate_launcher(std::move(delegate_launcher)) +{ +} + +HostProcess +MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) +{ + ProcessLaunchInfo resolved_info(launch_info); + + error.Clear(); + char exe_path[PATH_MAX]; + + PlatformSP host_platform_sp(Platform::GetHostPlatform()); + + const ArchSpec &arch_spec = resolved_info.GetArchitecture(); + + FileSpec exe_spec(resolved_info.GetExecutableFile()); + + FileSpec::FileType file_type = exe_spec.GetFileType(); + if (file_type != FileSpec::eFileTypeRegular) + { + ModuleSpec module_spec(exe_spec, arch_spec); + lldb::ModuleSP exe_module_sp; + error = host_platform_sp->ResolveExecutable(module_spec, exe_module_sp, NULL); + + if (error.Fail()) + return HostProcess(); + + if (exe_module_sp) + exe_spec = exe_module_sp->GetFileSpec(); + } + + if (exe_spec.Exists()) + { + exe_spec.GetPath(exe_path, sizeof(exe_path)); + } + else + { + resolved_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); + error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path); + return HostProcess(); + } + + resolved_info.SetExecutableFile(exe_spec, false); + assert(!resolved_info.GetFlags().Test(eLaunchFlagLaunchInTTY)); + + HostProcess process = m_delegate_launcher->LaunchProcess(resolved_info, error); + + if (process.GetProcessId() != LLDB_INVALID_PROCESS_ID) + { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + Host::MonitorChildProcessCallback callback = launch_info.GetMonitorProcessCallback(); + + void *baton = nullptr; + bool monitor_signals = false; + if (callback) + { + // If the ProcessLaunchInfo specified a callback, use that. + baton = launch_info.GetMonitorProcessBaton(); + monitor_signals = launch_info.GetMonitorSignals(); + } + else + { + callback = Process::SetProcessExitStatus; + } + + process.StartMonitoring(callback, baton, monitor_signals); + if (log) + log->PutCString("started monitoring child process."); + } + else + { + // Invalid process ID, something didn't go well + if (error.Success()) + error.SetErrorString("process launch failed for unknown reasons"); + } + return process; +} diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp index b7a77266c58c..e192f19a8896 100644 --- a/source/Host/common/NativeProcessProtocol.cpp +++ b/source/Host/common/NativeProcessProtocol.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Log.h" #include "lldb/Core/State.h" +#include "lldb/Host/Host.h" #include "lldb/Target/NativeRegisterContext.h" #include "NativeThreadProtocol.h" @@ -43,6 +44,18 @@ NativeProcessProtocol::NativeProcessProtocol (lldb::pid_t pid) : { } +lldb_private::Error +NativeProcessProtocol::Interrupt () +{ + Error error; +#if !defined (SIGSTOP) + error.SetErrorString ("local host does not support signaling"); + return error; +#else + return Signal (SIGSTOP); +#endif +} + lldb_private::Error NativeProcessProtocol::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info) { @@ -110,9 +123,8 @@ NativeProcessProtocol::GetThreadAtIndex (uint32_t idx) } NativeThreadProtocolSP -NativeProcessProtocol::GetThreadByID (lldb::tid_t tid) +NativeProcessProtocol::GetThreadByIDUnlocked (lldb::tid_t tid) { - Mutex::Locker locker (m_threads_mutex); for (auto thread_sp : m_threads) { if (thread_sp->GetID() == tid) @@ -121,6 +133,13 @@ NativeProcessProtocol::GetThreadByID (lldb::tid_t tid) return NativeThreadProtocolSP (); } +NativeThreadProtocolSP +NativeProcessProtocol::GetThreadByID (lldb::tid_t tid) +{ + Mutex::Locker locker (m_threads_mutex); + return GetThreadByIDUnlocked (tid); +} + bool NativeProcessProtocol::IsAlive () const { diff --git a/source/Host/common/NativeProcessProtocol.h b/source/Host/common/NativeProcessProtocol.h index 035a264e172e..19d8f353b26f 100644 --- a/source/Host/common/NativeProcessProtocol.h +++ b/source/Host/common/NativeProcessProtocol.h @@ -59,17 +59,25 @@ namespace lldb_private //------------------------------------------------------------------ /// Sends a process a UNIX signal \a signal. /// - /// Implementer note: the WillSignal ()/DidSignal () calls - /// from the Process class are not replicated here since no - /// concrete classes implemented any behavior for those and - /// put all the work in DoSignal (...). - /// /// @return /// Returns an error object. //------------------------------------------------------------------ virtual Error Signal (int signo) = 0; + //------------------------------------------------------------------ + /// Tells a process to interrupt all operations as if by a Ctrl-C. + /// + /// The default implementation will send a local host's equivalent of + /// a SIGSTOP to the process via the NativeProcessProtocol::Signal() + /// operation. + /// + /// @return + /// Returns an error object. + //------------------------------------------------------------------ + virtual Error + Interrupt (); + virtual Error Kill () = 0; @@ -296,7 +304,7 @@ namespace lldb_private void SetState (lldb::StateType state, bool notify_delegates = true); - // Derived classes need not impelment this. It can be used as a + // Derived classes need not implement this. It can be used as a // hook to clear internal caches that should be invalidated when // stop ids change. // @@ -323,6 +331,9 @@ namespace lldb_private void NotifyDidExec (); + NativeThreadProtocolSP + GetThreadByIDUnlocked (lldb::tid_t tid); + private: void diff --git a/source/Host/common/NativeThreadProtocol.h b/source/Host/common/NativeThreadProtocol.h index 9b404be500b9..15ecffe8b82d 100644 --- a/source/Host/common/NativeThreadProtocol.h +++ b/source/Host/common/NativeThreadProtocol.h @@ -31,7 +31,7 @@ namespace lldb_private { } - virtual const char * + virtual std::string GetName() = 0; virtual lldb::StateType diff --git a/source/Host/common/Pipe.cpp b/source/Host/common/Pipe.cpp deleted file mode 100644 index 4db0e32c93b7..000000000000 --- a/source/Host/common/Pipe.cpp +++ /dev/null @@ -1,171 +0,0 @@ -//===-- Pipe.cpp ------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/Pipe.h" - -#if defined(_WIN32) -#include -#include -#else -#include -#endif - -using namespace lldb_private; - -int Pipe::kInvalidDescriptor = -1; - -enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE - -Pipe::Pipe() -{ - m_fds[READ] = Pipe::kInvalidDescriptor; - m_fds[WRITE] = Pipe::kInvalidDescriptor; -} - -Pipe::~Pipe() -{ - Close(); -} - -bool -Pipe::Open() -{ - if (IsValid()) - return true; - -#ifdef _WIN32 - if (::_pipe(m_fds, 256, O_BINARY) == 0) - return true; -#else - if (::pipe(m_fds) == 0) - return true; -#endif - m_fds[READ] = Pipe::kInvalidDescriptor; - m_fds[WRITE] = Pipe::kInvalidDescriptor; - return false; -} - -int -Pipe::GetReadFileDescriptor() const -{ - return m_fds[READ]; -} - -int -Pipe::GetWriteFileDescriptor() const -{ - return m_fds[WRITE]; -} - -int -Pipe::ReleaseReadFileDescriptor() -{ - const int fd = m_fds[READ]; - m_fds[READ] = Pipe::kInvalidDescriptor; - return fd; -} - -int -Pipe::ReleaseWriteFileDescriptor() -{ - const int fd = m_fds[WRITE]; - m_fds[WRITE] = Pipe::kInvalidDescriptor; - return fd; -} - -void -Pipe::Close() -{ - CloseReadFileDescriptor(); - CloseWriteFileDescriptor(); -} - -bool -Pipe::ReadDescriptorIsValid() const -{ - return m_fds[READ] != Pipe::kInvalidDescriptor; -} - -bool -Pipe::WriteDescriptorIsValid() const -{ - return m_fds[WRITE] != Pipe::kInvalidDescriptor; -} - -bool -Pipe::IsValid() const -{ - return ReadDescriptorIsValid() && WriteDescriptorIsValid(); -} - -bool -Pipe::CloseReadFileDescriptor() -{ - if (ReadDescriptorIsValid()) - { - int err; -#ifdef _WIN32 - err = _close(m_fds[READ]); -#else - err = close(m_fds[READ]); -#endif - m_fds[READ] = Pipe::kInvalidDescriptor; - return err == 0; - } - return true; -} - -bool -Pipe::CloseWriteFileDescriptor() -{ - if (WriteDescriptorIsValid()) - { - int err; -#ifdef _WIN32 - err = _close(m_fds[WRITE]); -#else - err = close(m_fds[WRITE]); -#endif - m_fds[WRITE] = Pipe::kInvalidDescriptor; - return err == 0; - } - return true; -} - - -size_t -Pipe::Read (void *buf, size_t num_bytes) -{ - if (ReadDescriptorIsValid()) - { - const int fd = GetReadFileDescriptor(); -#ifdef _WIN32 - return _read (fd, (char *)buf, num_bytes); -#else - return read (fd, buf, num_bytes); -#endif - } - return 0; // Return 0 since errno won't be set if we didn't call read -} - -size_t -Pipe::Write (const void *buf, size_t num_bytes) -{ - if (WriteDescriptorIsValid()) - { - const int fd = GetWriteFileDescriptor(); -#ifdef _WIN32 - return _write (fd, (char *)buf, num_bytes); -#else - return write (fd, buf, num_bytes); -#endif - } - return 0; // Return 0 since errno won't be set if we didn't call write -} - diff --git a/source/Host/common/PipeBase.cpp b/source/Host/common/PipeBase.cpp new file mode 100644 index 000000000000..a9d6e6f46c86 --- /dev/null +++ b/source/Host/common/PipeBase.cpp @@ -0,0 +1,27 @@ +//===-- source/Host/common/PipeBase.cpp -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/PipeBase.h" + +using namespace lldb_private; + + +PipeBase::~PipeBase() = default; + +Error +PipeBase::OpenAsWriter(llvm::StringRef name, bool child_process_inherit) +{ + return OpenAsWriterWithTimeout(name, child_process_inherit, std::chrono::microseconds::zero()); +} + +Error +PipeBase::Read(void *buf, size_t size, size_t &bytes_read) +{ + return ReadWithTimeout(buf, size, std::chrono::microseconds::zero(), bytes_read); +} diff --git a/source/Host/common/Socket.cpp b/source/Host/common/Socket.cpp index 31e3228497ec..a6118eef7b79 100644 --- a/source/Host/common/Socket.cpp +++ b/source/Host/common/Socket.cpp @@ -18,6 +18,14 @@ #include "lldb/Host/TimeValue.h" #include "lldb/Interpreter/Args.h" +#ifdef __ANDROID_NDK__ +#include +#include +#include +#include +#include +#endif + #ifndef LLDB_DISABLE_POSIX #include #include @@ -40,6 +48,40 @@ typedef void * get_socket_option_arg_type; const NativeSocket Socket::kInvalidSocketValue = -1; #endif // #if defined(_WIN32) +#ifdef __ANDROID__ +// Android does not have SUN_LEN +#ifndef SUN_LEN +#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path)) +#endif +#endif // #ifdef __ANDROID__ + +namespace { + +NativeSocket CreateSocket(const int domain, const int type, const int protocol, bool child_processes_inherit) +{ + auto socketType = type; +#ifdef SOCK_CLOEXEC + if (!child_processes_inherit) { + socketType |= SOCK_CLOEXEC; + } +#endif + return ::socket (domain, socketType, protocol); +} + +NativeSocket Accept(NativeSocket sockfd, struct sockaddr *addr, socklen_t *addrlen, bool child_processes_inherit) +{ +#ifdef SOCK_CLOEXEC + int flags = 0; + if (!child_processes_inherit) { + flags |= SOCK_CLOEXEC; + } + return ::accept4 (sockfd, addr, addrlen, flags); +#else + return ::accept (sockfd, addr, addrlen); +#endif +} +} + Socket::Socket(NativeSocket socket, SocketProtocol protocol, bool should_close) : IOObject(eFDTypeSocket, should_close) , m_protocol(protocol) @@ -53,7 +95,7 @@ Socket::~Socket() Close(); } -Error Socket::TcpConnect(llvm::StringRef host_and_port, Socket *&socket) +Error Socket::TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) { // Store the result in a unique_ptr in case we error out, the memory will get correctly freed. std::unique_ptr final_socket; @@ -71,7 +113,7 @@ Error Socket::TcpConnect(llvm::StringRef host_and_port, Socket *&socket) return error; // Create the socket - sock = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + sock = CreateSocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, child_processes_inherit); if (sock == kInvalidSocketValue) { // TODO: On Windows, use WSAGetLastError(). @@ -125,7 +167,7 @@ Error Socket::TcpConnect(llvm::StringRef host_and_port, Socket *&socket) return error; } -Error Socket::TcpListen(llvm::StringRef host_and_port, Socket *&socket, Predicate* predicate) +Error Socket::TcpListen(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket, Predicate* predicate) { std::unique_ptr listen_socket; NativeSocket listen_sock = kInvalidSocketValue; @@ -134,7 +176,7 @@ Error Socket::TcpListen(llvm::StringRef host_and_port, Socket *&socket, Predicat const sa_family_t family = AF_INET; const int socktype = SOCK_STREAM; const int protocol = IPPROTO_TCP; - listen_sock = ::socket (family, socktype, protocol); + listen_sock = ::CreateSocket (family, socktype, protocol, child_processes_inherit); if (listen_sock == kInvalidSocketValue) { error.SetErrorToErrno(); @@ -196,7 +238,7 @@ Error Socket::TcpListen(llvm::StringRef host_and_port, Socket *&socket, Predicat return error; } -Error Socket::BlockingAccept(llvm::StringRef host_and_port, Socket *&socket) +Error Socket::BlockingAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) { Error error; std::string host_str; @@ -235,7 +277,10 @@ Error Socket::BlockingAccept(llvm::StringRef host_and_port, Socket *&socket) #endif socklen_t accept_addr_len = sizeof accept_addr; - int sock = ::accept (this->GetNativeSocket(), (struct sockaddr *)&accept_addr, &accept_addr_len); + int sock = Accept (this->GetNativeSocket(), + (struct sockaddr *)&accept_addr, + &accept_addr_len, + child_processes_inherit); if (sock == kInvalidSocketValue) { @@ -280,7 +325,7 @@ Error Socket::BlockingAccept(llvm::StringRef host_and_port, Socket *&socket) } -Error Socket::UdpConnect(llvm::StringRef host_and_port, Socket *&send_socket, Socket *&recv_socket) +Error Socket::UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket) { std::unique_ptr final_send_socket; std::unique_ptr final_recv_socket; @@ -300,7 +345,7 @@ Error Socket::UdpConnect(llvm::StringRef host_and_port, Socket *&send_socket, So // Setup the receiving end of the UDP connection on this localhost // on port zero. After we bind to port zero we can read the port. - final_recv_fd = ::socket (AF_INET, SOCK_DGRAM, 0); + final_recv_fd = ::CreateSocket (AF_INET, SOCK_DGRAM, 0, child_processes_inherit); if (final_recv_fd == kInvalidSocketValue) { // Socket creation failed... @@ -351,9 +396,10 @@ Error Socket::UdpConnect(llvm::StringRef host_and_port, Socket *&send_socket, So service_info_ptr != NULL; service_info_ptr = service_info_ptr->ai_next) { - final_send_fd = ::socket (service_info_ptr->ai_family, - service_info_ptr->ai_socktype, - service_info_ptr->ai_protocol); + final_send_fd = ::CreateSocket (service_info_ptr->ai_family, + service_info_ptr->ai_socktype, + service_info_ptr->ai_protocol, + child_processes_inherit); if (final_send_fd != kInvalidSocketValue) { @@ -380,7 +426,7 @@ Error Socket::UdpConnect(llvm::StringRef host_and_port, Socket *&send_socket, So return error; } -Error Socket::UnixDomainConnect(llvm::StringRef name, Socket *&socket) +Error Socket::UnixDomainConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) { Error error; #ifndef LLDB_DISABLE_POSIX @@ -388,7 +434,7 @@ Error Socket::UnixDomainConnect(llvm::StringRef name, Socket *&socket) // Open the socket that was passed in as an option struct sockaddr_un saddr_un; - int fd = ::socket (AF_UNIX, SOCK_STREAM, 0); + int fd = ::CreateSocket (AF_UNIX, SOCK_STREAM, 0, child_processes_inherit); if (fd == kInvalidSocketValue) { error.SetErrorToErrno(); @@ -417,7 +463,7 @@ Error Socket::UnixDomainConnect(llvm::StringRef name, Socket *&socket) return error; } -Error Socket::UnixDomainAccept(llvm::StringRef name, Socket *&socket) +Error Socket::UnixDomainAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) { Error error; #ifndef LLDB_DISABLE_POSIX @@ -427,7 +473,7 @@ Error Socket::UnixDomainAccept(llvm::StringRef name, Socket *&socket) NativeSocket listen_fd = kInvalidSocketValue; NativeSocket socket_fd = kInvalidSocketValue; - listen_fd = ::socket (AF_UNIX, SOCK_STREAM, 0); + listen_fd = ::CreateSocket (AF_UNIX, SOCK_STREAM, 0, child_processes_inherit); if (listen_fd == kInvalidSocketValue) { error.SetErrorToErrno(); @@ -449,7 +495,7 @@ Error Socket::UnixDomainAccept(llvm::StringRef name, Socket *&socket) { if (::listen (listen_fd, 5) == 0) { - socket_fd = ::accept (listen_fd, NULL, 0); + socket_fd = Accept (listen_fd, NULL, 0, child_processes_inherit); if (socket_fd > 0) { final_socket.reset(new Socket(socket_fd, ProtocolUnixDomain, true)); diff --git a/source/Host/common/SocketAddress.cpp b/source/Host/common/SocketAddress.cpp index a952a83185fb..6231631934df 100644 --- a/source/Host/common/SocketAddress.cpp +++ b/source/Host/common/SocketAddress.cpp @@ -214,6 +214,8 @@ SocketAddress::getaddrinfo (const char *host, int ai_protocol, int ai_flags) { + Clear (); + struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = ai_family; @@ -221,15 +223,17 @@ SocketAddress::getaddrinfo (const char *host, hints.ai_protocol = ai_protocol; hints.ai_flags = ai_flags; + bool result = false; struct addrinfo *service_info_list = NULL; int err = ::getaddrinfo (host, service, &hints, &service_info_list); if (err == 0 && service_info_list) + { *this = service_info_list; - else - Clear(); + result = IsValid (); + } :: freeaddrinfo (service_info_list); - return IsValid(); + return result; } diff --git a/source/Host/common/SoftwareBreakpoint.cpp b/source/Host/common/SoftwareBreakpoint.cpp index fe2f504ebc71..d9d1fa67156f 100644 --- a/source/Host/common/SoftwareBreakpoint.cpp +++ b/source/Host/common/SoftwareBreakpoint.cpp @@ -119,6 +119,16 @@ SoftwareBreakpoint::EnableSoftwareBreakpoint (NativeProcessProtocol &process, ll return Error ("SoftwareBreakpoint::%s failed to read memory while attempting to set breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, bytes_read); } + // Log what we read. + if (log) + { + int i = 0; + for (const uint8_t *read_byte = saved_opcode_bytes; read_byte < saved_opcode_bytes + bp_opcode_size; ++read_byte) + { + log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " ovewriting byte index %d (was 0x%x)", __FUNCTION__, addr, i++, static_cast (*read_byte)); + } + } + // Write a software breakpoint in place of the original opcode. lldb::addr_t bytes_written = 0; error = process.WriteMemory (addr, bp_opcode_bytes, static_cast (bp_opcode_size), bytes_written); @@ -207,7 +217,7 @@ SoftwareBreakpoint::DoDisable () if (m_opcode_size > 0) { - // Clear a software breakoint instruction + // Clear a software breakpoint instruction uint8_t curr_break_op [MAX_TRAP_OPCODE_SIZE]; bool break_op_found = false; assert (m_opcode_size <= sizeof (curr_break_op)); @@ -265,7 +275,14 @@ SoftwareBreakpoint::DoDisable () { // SUCCESS if (log) + { + int i = 0; + for (const uint8_t *verify_byte = verify_opcode; verify_byte < verify_opcode + m_opcode_size; ++verify_byte) + { + log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " replaced byte index %d with 0x%x", __FUNCTION__, m_addr, i++, static_cast (*verify_byte)); + } log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", __FUNCTION__, m_addr); + } return error; } else diff --git a/source/Host/common/ThisThread.cpp b/source/Host/common/ThisThread.cpp new file mode 100644 index 000000000000..289ec780e9fb --- /dev/null +++ b/source/Host/common/ThisThread.cpp @@ -0,0 +1,52 @@ +//===-- ThisThread.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Error.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Host/ThisThread.h" + +#include "llvm/ADT/STLExtras.h" + +#include + +using namespace lldb; +using namespace lldb_private; + +void +ThisThread::SetName(llvm::StringRef name, int max_length) +{ + std::string truncated_name(name.data()); + + // Thread names are coming in like '' and + // ''. So just chopping the end of the string + // off leads to a lot of similar named threads. Go through the thread name + // and search for the last dot and use that. + + if (max_length > 0 && truncated_name.length() > static_cast(max_length)) + { + // First see if we can get lucky by removing any initial or final braces. + std::string::size_type begin = truncated_name.find_first_not_of("(<"); + std::string::size_type end = truncated_name.find_last_not_of(")>."); + if (end - begin > static_cast(max_length)) + { + // We're still too long. Since this is a dotted component, use everything after the last + // dot, up to a maximum of |length| characters. + std::string::size_type last_dot = truncated_name.find_last_of("."); + if (last_dot != std::string::npos) + begin = last_dot + 1; + + end = std::min(end, begin + max_length); + } + + std::string::size_type count = end - begin + 1; + truncated_name = truncated_name.substr(begin, count); + } + + SetName(truncated_name.c_str()); +} diff --git a/source/Host/common/ThreadLauncher.cpp b/source/Host/common/ThreadLauncher.cpp new file mode 100644 index 000000000000..ec7da325bf92 --- /dev/null +++ b/source/Host/common/ThreadLauncher.cpp @@ -0,0 +1,74 @@ +//===-- ThreadLauncher.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// lldb Includes +#include "lldb/Core/Log.h" +#include "lldb/Host/HostNativeThread.h" +#include "lldb/Host/HostThread.h" +#include "lldb/Host/ThisThread.h" +#include "lldb/Host/ThreadLauncher.h" + +#if defined(_WIN32) +#include "lldb/Host/windows/windows.h" +#endif + +using namespace lldb; +using namespace lldb_private; + +HostThread +ThreadLauncher::LaunchThread(llvm::StringRef name, lldb::thread_func_t thread_function, lldb::thread_arg_t thread_arg, Error *error_ptr, size_t min_stack_byte_size) +{ + Error error; + if (error_ptr) + error_ptr->Clear(); + + // Host::ThreadCreateTrampoline will delete this pointer for us. + HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo(name.data(), thread_function, thread_arg); + lldb::thread_t thread; +#ifdef _WIN32 + thread = + (lldb::thread_t)::_beginthreadex(0, (unsigned)min_stack_byte_size, HostNativeThread::ThreadCreateTrampoline, info_ptr, 0, NULL); + if (thread == (lldb::thread_t)(-1L)) + error.SetError(::GetLastError(), eErrorTypeWin32); +#else + + pthread_attr_t *thread_attr_ptr = NULL; + pthread_attr_t thread_attr; + bool destroy_attr = false; + if (min_stack_byte_size > 0) + { + if (::pthread_attr_init (&thread_attr) == 0) + { + destroy_attr = true; + size_t default_min_stack_byte_size = 0; + if (::pthread_attr_getstacksize(&thread_attr, &default_min_stack_byte_size) == 0) + { + if (default_min_stack_byte_size < min_stack_byte_size) + { + if (::pthread_attr_setstacksize (&thread_attr, min_stack_byte_size) == 0) + thread_attr_ptr = &thread_attr; + } + } + + } + } + int err = ::pthread_create(&thread, thread_attr_ptr, HostNativeThread::ThreadCreateTrampoline, info_ptr); + + if (destroy_attr) + ::pthread_attr_destroy(&thread_attr); + + error.SetError(err, eErrorTypePOSIX); +#endif + if (error_ptr) + *error_ptr = error; + if (!error.Success()) + thread = LLDB_INVALID_HOST_THREAD; + + return HostThread(thread); +} diff --git a/source/Host/freebsd/Host.cpp b/source/Host/freebsd/Host.cpp index dc092e86d78b..2cbf4d8f4696 100644 --- a/source/Host/freebsd/Host.cpp +++ b/source/Host/freebsd/Host.cpp @@ -50,80 +50,6 @@ extern "C" { using namespace lldb; using namespace lldb_private; -class FreeBSDThread -{ -public: - FreeBSDThread(const char *thread_name) - { - Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name); - } - static void PThreadDestructor (void *v) - { - delete (FreeBSDThread*)v; - } -}; - -static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT; -static pthread_key_t g_thread_create_key = 0; - -static void -InitThreadCreated() -{ - ::pthread_key_create (&g_thread_create_key, FreeBSDThread::PThreadDestructor); -} - -void -Host::ThreadCreated (const char *thread_name) -{ - ::pthread_once (&g_thread_create_once, InitThreadCreated); - if (g_thread_create_key) - { - ::pthread_setspecific (g_thread_create_key, new FreeBSDThread(thread_name)); - } - - Host::SetShortThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name, 16); -} - -std::string -Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid) -{ - struct kinfo_proc *kp = nullptr, *nkp; - size_t len = 0; - int error; - int name[4] = { - CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD, (int)pid - }; - - while (1) { - error = sysctl(name, 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 std::string(); - } - kp = nkp; - continue; - } - if (error != 0) - len = 0; - break; - } - - std::string thread_name; - for (size_t i = 0; i < len / sizeof(*kp); i++) { - if (kp[i].ki_tid == (int)tid) { - thread_name = kp[i].ki_tdname; - break; - } - } - free(kp); - return thread_name; -} - void Host::Backtrace (Stream &strm, uint32_t max_frames) { @@ -363,43 +289,19 @@ Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) { - int mib[2] = { CTL_KERN, KERN_PS_STRINGS }; - void *ps_strings_addr, *auxv_addr; - size_t ps_strings_size = sizeof(void *); - Elf_Auxinfo aux_info[AT_COUNT]; - struct ps_strings ps_strings; - struct ptrace_io_desc pid; + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_AUXV, 0 }; + size_t auxv_size = AT_COUNT * sizeof(Elf_Auxinfo); DataBufferSP buf_sp; - std::unique_ptr buf_ap(new DataBufferHeap(1024, 0)); - - if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) { - pid.piod_op = PIOD_READ_D; - pid.piod_addr = &ps_strings; - pid.piod_offs = ps_strings_addr; - pid.piod_len = sizeof(ps_strings); - if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) { - perror("failed to fetch ps_strings"); - buf_ap.release(); - goto done; - } - - auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1; - - pid.piod_addr = aux_info; - pid.piod_offs = auxv_addr; - pid.piod_len = sizeof(aux_info); - if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) { - perror("failed to fetch aux_info"); - buf_ap.release(); - goto done; - } - memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len); + + std::unique_ptr buf_ap(new DataBufferHeap(auxv_size, 0)); + + mib[3] = process->GetID(); + if (::sysctl(mib, 4, buf_ap->GetBytes(), &auxv_size, NULL, 0) == 0) { buf_sp.reset(buf_ap.release()); } else { - perror("sysctl failed on ps_strings"); + perror("sysctl failed on auxv"); } - done: return buf_sp; } diff --git a/source/Host/freebsd/HostInfoFreeBSD.cpp b/source/Host/freebsd/HostInfoFreeBSD.cpp index 78458259f0a2..d51109320c3b 100644 --- a/source/Host/freebsd/HostInfoFreeBSD.cpp +++ b/source/Host/freebsd/HostInfoFreeBSD.cpp @@ -17,6 +17,12 @@ using namespace lldb_private; +uint32_t +HostInfoFreeBSD::GetMaxThreadNameLength() +{ + return 16; +} + bool HostInfoFreeBSD::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update) { diff --git a/source/Host/freebsd/HostThreadFreeBSD.cpp b/source/Host/freebsd/HostThreadFreeBSD.cpp new file mode 100644 index 000000000000..7d611bb6894b --- /dev/null +++ b/source/Host/freebsd/HostThreadFreeBSD.cpp @@ -0,0 +1,77 @@ +//===-- HostThreadFreeBSD.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// lldb Includes +#include "lldb/Host/freebsd/HostThreadFreeBSD.h" +#include "lldb/Host/Host.h" + +// C includes +#include +#include +#include +#include +#include +#include + +// C++ includes +#include + +using namespace lldb_private; + +HostThreadFreeBSD::HostThreadFreeBSD() +{ +} + +HostThreadFreeBSD::HostThreadFreeBSD(lldb::thread_t thread) + : HostThreadPosix(thread) +{ +} + +void +HostThreadFreeBSD::GetName(lldb::tid_t tid, llvm::SmallVectorImpl &name) +{ + name.clear(); + int pid = Host::GetCurrentProcessID(); + + 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, (int)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; + } + 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)tid) + { + name.append(kp[i].ki_tdname, kp[i].ki_tdname + strlen(kp[i].ki_tdname)); + break; + } + } + free(kp); +} diff --git a/source/Host/freebsd/ThisThread.cpp b/source/Host/freebsd/ThisThread.cpp new file mode 100644 index 000000000000..fb25847be24f --- /dev/null +++ b/source/Host/freebsd/ThisThread.cpp @@ -0,0 +1,30 @@ +//===-- ThisThread.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/HostNativeThread.h" +#include "lldb/Host/ThisThread.h" + +#include "llvm/ADT/SmallVector.h" + +#include +#include + +using namespace lldb_private; + +void +ThisThread::SetName(llvm::StringRef name) +{ + ::pthread_set_name_np(::pthread_self(), name.data()); +} + +void +ThisThread::GetName(llvm::SmallVectorImpl &name) +{ + HostNativeThread::GetName(::pthread_getthreadid_np(), name); +} diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp new file mode 100644 index 000000000000..38ddc0a49220 --- /dev/null +++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -0,0 +1,797 @@ +//===-- ConnectionFileDescriptorPosix.cpp -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#if defined(__APPLE__) +// Enable this special support for Apple builds where we can have unlimited +// select bounds. We tried switching to poll() and kqueue and we were panicing +// the kernel, so we have to stick with select for now. +#define _DARWIN_UNLIMITED_SELECT +#endif + +#include "lldb/Host/posix/ConnectionFileDescriptorPosix.h" +#include "lldb/Host/Config.h" +#include "lldb/Host/IOObject.h" +#include "lldb/Host/SocketAddress.h" +#include "lldb/Host/Socket.h" + +// C Includes +#include +#include +#include +#include +#include + +#ifndef LLDB_DISABLE_POSIX +#include +#endif + +// C++ Includes +// Other libraries and framework includes +#include "llvm/Support/ErrorHandling.h" +#if defined(__APPLE__) +#include "llvm/ADT/SmallVector.h" +#endif +// Project includes +#include "lldb/lldb-private-log.h" +#include "lldb/Core/Communication.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Timer.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/Socket.h" +#include "lldb/Interpreter/Args.h" + +using namespace lldb; +using namespace lldb_private; + +ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit) + : Connection() + , m_pipe() + , m_mutex(Mutex::eMutexTypeRecursive) + , 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)); + if (log) + log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", static_cast(this)); +} + +ConnectionFileDescriptor::ConnectionFileDescriptor(int fd, bool owns_fd) + : Connection() + , m_pipe() + , m_mutex(Mutex::eMutexTypeRecursive) + , m_shutting_down(false) + , m_waiting_for_accept(false) + , m_child_processes_inherit(false) +{ + m_write_sp.reset(new File(fd, owns_fd)); + m_read_sp.reset(new File(fd, false)); + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)", static_cast(this), fd, + owns_fd); + OpenCommandPipe(); +} + +ConnectionFileDescriptor::~ConnectionFileDescriptor() +{ + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", static_cast(this)); + Disconnect(NULL); + CloseCommandPipe(); +} + +void +ConnectionFileDescriptor::OpenCommandPipe() +{ + CloseCommandPipe(); + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + // Make the command file descriptor here: + Error result = m_pipe.CreateNew(m_child_processes_inherit); + if (!result.Success()) + { + if (log) + log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe () - could not make pipe: %s", static_cast(this), + result.AsCString()); + } + else + { + if (log) + log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe() - success readfd=%d writefd=%d", static_cast(this), + m_pipe.GetReadFileDescriptor(), m_pipe.GetWriteFileDescriptor()); + } +} + +void +ConnectionFileDescriptor::CloseCommandPipe() +{ + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p ConnectionFileDescriptor::CloseCommandPipe()", static_cast(this)); + + m_pipe.Close(); +} + +bool +ConnectionFileDescriptor::IsConnected() const +{ + return (m_read_sp && m_read_sp->IsValid()) || (m_write_sp && m_write_sp->IsValid()); +} + +ConnectionStatus +ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) +{ + Mutex::Locker locker(m_mutex); + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p ConnectionFileDescriptor::Connect (url = '%s')", static_cast(this), s); + + OpenCommandPipe(); + + if (s && s[0]) + { + if (strstr(s, "listen://") == s) + { + // listen://HOST:PORT + return SocketListen(s + strlen("listen://"), error_ptr); + } + else if (strstr(s, "accept://") == s) + { + // unix://SOCKNAME + return NamedSocketAccept(s + strlen("accept://"), error_ptr); + } + else if (strstr(s, "unix-accept://") == s) + { + // unix://SOCKNAME + return NamedSocketAccept(s + strlen("unix-accept://"), error_ptr); + } + else if (strstr(s, "connect://") == s) + { + return ConnectTCP(s + strlen("connect://"), error_ptr); + } + else if (strstr(s, "tcp-connect://") == s) + { + return ConnectTCP(s + strlen("tcp-connect://"), error_ptr); + } + else if (strstr(s, "udp://") == s) + { + return ConnectUDP(s + strlen("udp://"), error_ptr); + } +#ifndef LLDB_DISABLE_POSIX + else if (strstr(s, "fd://") == s) + { + // Just passing a native file descriptor within this current process + // that is already opened (possibly from a service or other source). + s += strlen("fd://"); + bool success = false; + int fd = Args::StringToSInt32(s, -1, 0, &success); + + if (success) + { + // We have what looks to be a valid file descriptor, but we + // should make sure it is. We currently are doing this by trying to + // get the flags from the file descriptor and making sure it + // isn't a bad fd. + errno = 0; + int flags = ::fcntl(fd, F_GETFL, 0); + if (flags == -1 || errno == EBADF) + { + if (error_ptr) + error_ptr->SetErrorStringWithFormat("stale file descriptor: %s", s); + m_read_sp.reset(); + m_write_sp.reset(); + return eConnectionStatusError; + } + else + { + // Don't take ownership of a file descriptor that gets passed + // to us since someone else opened the file descriptor and + // handed it to us. + // TODO: Since are using a URL to open connection we should + // eventually parse options using the web standard where we + // have "fd://123?opt1=value;opt2=value" and we can have an + // option be "owns=1" or "owns=0" or something like this to + // allow us to specify this. For now, we assume we must + // assume we don't own it. + + std::unique_ptr tcp_socket; + tcp_socket.reset(new Socket(fd, Socket::ProtocolTcp, false)); + // Try and get a socket option from this file descriptor to + // see if this is a socket and set m_is_socket accordingly. + int resuse; + bool is_socket = !!tcp_socket->GetOption(SOL_SOCKET, SO_REUSEADDR, resuse); + if (is_socket) + { + m_read_sp = std::move(tcp_socket); + m_write_sp = m_read_sp; + } + else + { + m_read_sp.reset(new File(fd, false)); + m_write_sp.reset(new File(fd, false)); + } + return eConnectionStatusSuccess; + } + } + + if (error_ptr) + error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"fd://%s\"", s); + m_read_sp.reset(); + m_write_sp.reset(); + return eConnectionStatusError; + } + else if (strstr(s, "file://") == s) + { + // file:///PATH + const char *path = s + strlen("file://"); + int fd = -1; + do + { + fd = ::open(path, O_RDWR); + } while (fd == -1 && errno == EINTR); + + if (fd == -1) + { + if (error_ptr) + error_ptr->SetErrorToErrno(); + return eConnectionStatusError; + } + + if (::isatty(fd)) + { + // Set up serial terminal emulation + struct termios options; + ::tcgetattr(fd, &options); + + // Set port speed to maximum + ::cfsetospeed(&options, B115200); + ::cfsetispeed(&options, B115200); + + // Raw input, disable echo and signals + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + + // Make sure only one character is needed to return from a read + options.c_cc[VMIN] = 1; + options.c_cc[VTIME] = 0; + + ::tcsetattr(fd, TCSANOW, &options); + } + + int flags = ::fcntl(fd, F_GETFL, 0); + if (flags >= 0) + { + if ((flags & O_NONBLOCK) == 0) + { + flags |= O_NONBLOCK; + ::fcntl(fd, F_SETFL, flags); + } + } + m_read_sp.reset(new File(fd, true)); + m_write_sp.reset(new File(fd, false)); + return eConnectionStatusSuccess; + } +#endif + if (error_ptr) + error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'", s); + return eConnectionStatusError; + } + if (error_ptr) + error_ptr->SetErrorString("invalid connect arguments"); + return eConnectionStatusError; +} + +bool +ConnectionFileDescriptor::InterruptRead() +{ + size_t bytes_written = 0; + Error result = m_pipe.Write("i", 1, bytes_written); + return result.Success(); +} + +ConnectionStatus +ConnectionFileDescriptor::Disconnect(Error *error_ptr) +{ + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p ConnectionFileDescriptor::Disconnect ()", static_cast(this)); + + ConnectionStatus status = eConnectionStatusSuccess; + + if (!IsConnected()) + { + if (log) + log->Printf("%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", static_cast(this)); + return eConnectionStatusSuccess; + } + + if (m_read_sp && m_read_sp->IsValid() && m_read_sp->GetFdType() == IOObject::eFDTypeSocket) + static_cast(*m_read_sp).PreDisconnect(); + + // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is quite likely + // because somebody is doing a blocking read on our file descriptor. If that's the case, + // then send the "q" char to the command file channel so the read will wake up and the connection + // will then know to shut down. + + m_shutting_down = true; + + Mutex::Locker locker; + bool got_lock = locker.TryLock(m_mutex); + + if (!got_lock) + { + if (m_pipe.CanWrite()) + { + size_t bytes_written = 0; + Error result = m_pipe.Write("q", 1, bytes_written); + if (log) + log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, sent 'q' to %d, error = '%s'.", + static_cast(this), m_pipe.GetWriteFileDescriptor(), result.AsCString()); + } + else if (log) + { + log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, but no command pipe is available.", + static_cast(this)); + } + locker.Lock(m_mutex); + } + + Error error = m_read_sp->Close(); + Error error2 = m_write_sp->Close(); + if (error.Fail() || error2.Fail()) + status = eConnectionStatusError; + if (error_ptr) + *error_ptr = error.Fail() ? error : error2; + + m_shutting_down = false; + return status; +} + +size_t +ConnectionFileDescriptor::Read(void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr) +{ + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + + Mutex::Locker locker; + bool got_lock = locker.TryLock(m_mutex); + if (!got_lock) + { + if (log) + log->Printf("%p ConnectionFileDescriptor::Read () failed to get the connection lock.", static_cast(this)); + if (error_ptr) + error_ptr->SetErrorString("failed to get the connection lock for read."); + + status = eConnectionStatusTimedOut; + return 0; + } + else if (m_shutting_down) + return eConnectionStatusError; + + status = BytesAvailable(timeout_usec, error_ptr); + if (status != eConnectionStatusSuccess) + return 0; + + Error error; + size_t bytes_read = dst_len; + error = m_read_sp->Read(dst, bytes_read); + + if (log) + { + log->Printf("%p ConnectionFileDescriptor::Read() fd = %" PRIu64 ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s", + static_cast(this), static_cast(m_read_sp->GetWaitableHandle()), static_cast(dst), + static_cast(dst_len), static_cast(bytes_read), error.AsCString()); + } + + if (bytes_read == 0) + { + error.Clear(); // End-of-file. Do not automatically close; pass along for the end-of-file handlers. + status = eConnectionStatusEndOfFile; + } + + if (error_ptr) + *error_ptr = error; + + if (error.Fail()) + { + uint32_t error_value = error.GetError(); + switch (error_value) + { + case EAGAIN: // The file was marked for non-blocking I/O, and no data were ready to be read. + if (m_read_sp->GetFdType() == IOObject::eFDTypeSocket) + status = eConnectionStatusTimedOut; + else + status = eConnectionStatusSuccess; + return 0; + + case EFAULT: // Buf points outside the allocated address space. + case EINTR: // A read from a slow device was interrupted before any data arrived by the delivery of a signal. + case EINVAL: // The pointer associated with fildes was negative. + case EIO: // An I/O error occurred while reading from the file system. + // The process group is orphaned. + // The file is a regular file, nbyte is greater than 0, + // the starting position is before the end-of-file, and + // the starting position is greater than or equal to the + // offset maximum established for the open file + // descriptor associated with fildes. + case EISDIR: // An attempt is made to read a directory. + case ENOBUFS: // An attempt to allocate a memory buffer fails. + case ENOMEM: // Insufficient memory is available. + status = eConnectionStatusError; + break; // Break to close.... + + case ENOENT: // no such file or directory + case EBADF: // fildes is not a valid file or socket descriptor open for reading. + case ENXIO: // An action is requested of a device that does not exist.. + // A requested action cannot be performed by the device. + case ECONNRESET: // The connection is closed by the peer during a read attempt on a socket. + case ENOTCONN: // A read is attempted on an unconnected socket. + status = eConnectionStatusLostConnection; + break; // Break to close.... + + case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a socket. + status = eConnectionStatusTimedOut; + return 0; + + default: + if (log) + log->Printf("%p ConnectionFileDescriptor::Read (), unexpected error: %s", static_cast(this), + strerror(error_value)); + status = eConnectionStatusError; + break; // Break to close.... + } + + return 0; + } + return bytes_read; +} + +size_t +ConnectionFileDescriptor::Write(const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr) +{ + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 ")", static_cast(this), + static_cast(src), static_cast(src_len)); + + if (!IsConnected()) + { + if (error_ptr) + error_ptr->SetErrorString("not connected"); + status = eConnectionStatusNoConnection; + return 0; + } + + Error error; + + size_t bytes_sent = src_len; + error = m_write_sp->Write(src, bytes_sent); + + if (log) + { + log->Printf("%p ConnectionFileDescriptor::Write(fd = %" PRIu64 ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 " (error = %s)", + static_cast(this), static_cast(m_write_sp->GetWaitableHandle()), static_cast(src), + static_cast(src_len), static_cast(bytes_sent), error.AsCString()); + } + + if (error_ptr) + *error_ptr = error; + + if (error.Fail()) + { + switch (error.GetError()) + { + case EAGAIN: + case EINTR: + status = eConnectionStatusSuccess; + return 0; + + case ECONNRESET: // The connection is closed by the peer during a read attempt on a socket. + case ENOTCONN: // A read is attempted on an unconnected socket. + status = eConnectionStatusLostConnection; + break; // Break to close.... + + default: + status = eConnectionStatusError; + break; // Break to close.... + } + + return 0; + } + + status = eConnectionStatusSuccess; + return bytes_sent; +} + +// This ConnectionFileDescriptor::BytesAvailable() uses select(). +// +// PROS: +// - select is consistent across most unix platforms +// - The Apple specific version allows for unlimited fds in the fd_sets by +// setting the _DARWIN_UNLIMITED_SELECT define prior to including the +// required header files. +// CONS: +// - on non-Apple platforms, only supports file descriptors up to FD_SETSIZE. +// This implementation will assert if it runs into that hard limit to let +// users know that another ConnectionFileDescriptor::BytesAvailable() should +// be used or a new version of ConnectionFileDescriptor::BytesAvailable() +// should be written for the system that is running into the limitations. + +#if defined(__APPLE__) +#define FD_SET_DATA(fds) fds.data() +#else +#define FD_SET_DATA(fds) &fds +#endif + +ConnectionStatus +ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, Error *error_ptr) +{ + // Don't need to take the mutex here separately since we are only called from Read. If we + // ever get used more generally we will need to lock here as well. + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", static_cast(this), timeout_usec); + + struct timeval *tv_ptr; + struct timeval tv; + if (timeout_usec == UINT32_MAX) + { + // Inifinite wait... + tv_ptr = nullptr; + } + else + { + TimeValue time_value; + time_value.OffsetWithMicroSeconds(timeout_usec); + tv.tv_sec = time_value.seconds(); + tv.tv_usec = time_value.microseconds(); + tv_ptr = &tv; + } + + // Make a copy of the file descriptors to make sure we don't + // have another thread change these values out from under us + // and cause problems in the loop below where like in FS_SET() + const IOObject::WaitableHandle handle = m_read_sp->GetWaitableHandle(); + const int pipe_fd = m_pipe.GetReadFileDescriptor(); + + if (handle != IOObject::kInvalidHandleValue) + { +#if defined(_MSC_VER) + // select() won't accept pipes on Windows. The entire Windows codepath needs to be + // converted over to using WaitForMultipleObjects and event HANDLEs, but for now at least + // this will allow ::select() to not return an error. + const bool have_pipe_fd = false; +#else + const bool have_pipe_fd = pipe_fd >= 0; +#if !defined(__APPLE__) + assert(handle < FD_SETSIZE); + if (have_pipe_fd) + assert(pipe_fd < FD_SETSIZE); +#endif +#endif + while (handle == m_read_sp->GetWaitableHandle()) + { + const int nfds = std::max(handle, pipe_fd) + 1; +#if defined(__APPLE__) + llvm::SmallVector read_fds; + read_fds.resize((nfds / FD_SETSIZE) + 1); + for (size_t i = 0; i < read_fds.size(); ++i) + FD_ZERO(&read_fds[i]); +// FD_SET doesn't bounds check, it just happily walks off the end +// but we have taken care of making the extra storage with our +// SmallVector of fd_set objects +#else + fd_set read_fds; + FD_ZERO(&read_fds); +#endif + FD_SET(handle, FD_SET_DATA(read_fds)); + if (have_pipe_fd) + FD_SET(pipe_fd, FD_SET_DATA(read_fds)); + + Error error; + + if (log) + { + if (have_pipe_fd) + log->Printf( + "%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i, %i}, NULL, NULL, timeout=%p)...", + static_cast(this), nfds, handle, pipe_fd, static_cast(tv_ptr)); + else + log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p)...", + static_cast(this), nfds, handle, static_cast(tv_ptr)); + } + + const int num_set_fds = ::select(nfds, FD_SET_DATA(read_fds), NULL, NULL, tv_ptr); + if (num_set_fds < 0) + error.SetErrorToErrno(); + else + error.Clear(); + + if (log) + { + if (have_pipe_fd) + log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i, %i}, NULL, NULL, timeout=%p) " + "=> %d, error = %s", + static_cast(this), nfds, handle, pipe_fd, static_cast(tv_ptr), num_set_fds, + error.AsCString()); + else + log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p) => " + "%d, error = %s", + static_cast(this), nfds, handle, static_cast(tv_ptr), num_set_fds, error.AsCString()); + } + + if (error_ptr) + *error_ptr = error; + + if (error.Fail()) + { + switch (error.GetError()) + { + case EBADF: // One of the descriptor sets specified an invalid descriptor. + return eConnectionStatusLostConnection; + + case EINVAL: // The specified time limit is invalid. One of its components is negative or too large. + default: // Other unknown error + return eConnectionStatusError; + + case EAGAIN: // The kernel was (perhaps temporarily) unable to + // allocate the requested number of file descriptors, + // or we have non-blocking IO + case EINTR: // A signal was delivered before the time limit + // expired and before any of the selected events + // occurred. + break; // Lets keep reading to until we timeout + } + } + else if (num_set_fds == 0) + { + return eConnectionStatusTimedOut; + } + else if (num_set_fds > 0) + { + if (FD_ISSET(handle, FD_SET_DATA(read_fds))) + return eConnectionStatusSuccess; + if (have_pipe_fd && FD_ISSET(pipe_fd, FD_SET_DATA(read_fds))) + { + // We got a command to exit. Read the data from that pipe: + char buffer[16]; + ssize_t bytes_read; + + do + { + bytes_read = ::read(pipe_fd, buffer, sizeof(buffer)); + } while (bytes_read < 0 && errno == EINTR); + + switch (buffer[0]) + { + case 'q': + if (log) + log->Printf("%p ConnectionFileDescriptor::BytesAvailable() got data: %*s from the command channel.", + static_cast(this), static_cast(bytes_read), buffer); + return eConnectionStatusEndOfFile; + case 'i': + // Interrupt the current read + return eConnectionStatusInterrupted; + } + } + } + } + } + + if (error_ptr) + error_ptr->SetErrorString("not connected"); + return eConnectionStatusLostConnection; +} + +ConnectionStatus +ConnectionFileDescriptor::NamedSocketAccept(const char *socket_name, Error *error_ptr) +{ + Socket *socket = nullptr; + Error error = Socket::UnixDomainAccept(socket_name, m_child_processes_inherit, socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; +} + +ConnectionStatus +ConnectionFileDescriptor::NamedSocketConnect(const char *socket_name, Error *error_ptr) +{ + Socket *socket = nullptr; + Error error = Socket::UnixDomainConnect(socket_name, m_child_processes_inherit, socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; +} + +ConnectionStatus +ConnectionFileDescriptor::SocketListen(const char *s, Error *error_ptr) +{ + m_port_predicate.SetValue(0, eBroadcastNever); + + Socket *socket = nullptr; + m_waiting_for_accept = true; + Error error = Socket::TcpListen(s, m_child_processes_inherit, socket, &m_port_predicate); + if (error_ptr) + *error_ptr = error; + if (error.Fail()) + return eConnectionStatusError; + + std::unique_ptr listening_socket_up; + + listening_socket_up.reset(socket); + socket = nullptr; + error = listening_socket_up->BlockingAccept(s, m_child_processes_inherit, socket); + listening_socket_up.reset(); + if (error_ptr) + *error_ptr = error; + if (error.Fail()) + return eConnectionStatusError; + + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; +} + +ConnectionStatus +ConnectionFileDescriptor::ConnectTCP(const char *s, Error *error_ptr) +{ + Socket *socket = nullptr; + Error error = Socket::TcpConnect(s, m_child_processes_inherit, socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; +} + +ConnectionStatus +ConnectionFileDescriptor::ConnectUDP(const char *s, Error *error_ptr) +{ + Socket *send_socket = nullptr; + Socket *recv_socket = nullptr; + Error error = Socket::UdpConnect(s, m_child_processes_inherit, send_socket, recv_socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(send_socket); + m_read_sp.reset(recv_socket); + return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; +} + +uint16_t +ConnectionFileDescriptor::GetListeningPort(uint32_t timeout_sec) +{ + uint16_t bound_port = 0; + if (timeout_sec == UINT32_MAX) + m_port_predicate.WaitForValueNotEqualTo(0, bound_port); + else + { + TimeValue timeout = TimeValue::Now(); + timeout.OffsetWithSeconds(timeout_sec); + m_port_predicate.WaitForValueNotEqualTo(0, bound_port, &timeout); + } + return bound_port; +} + +bool +ConnectionFileDescriptor::GetChildProcessesInherit() const +{ + return m_child_processes_inherit; +} + +void +ConnectionFileDescriptor::SetChildProcessesInherit(bool child_processes_inherit) +{ + m_child_processes_inherit = child_processes_inherit; +} diff --git a/source/Host/posix/HostInfoPosix.cpp b/source/Host/posix/HostInfoPosix.cpp index 77fdc2b61a31..018d423ee9d3 100644 --- a/source/Host/posix/HostInfoPosix.cpp +++ b/source/Host/posix/HostInfoPosix.cpp @@ -69,6 +69,7 @@ HostInfoPosix::LookupUserName(uint32_t uid, std::string &user_name) const char * HostInfoPosix::LookupGroupName(uint32_t gid, std::string &group_name) { +#ifndef __ANDROID__ char group_buffer[PATH_MAX]; size_t group_buffer_size = sizeof(group_buffer); struct group group_info; @@ -94,6 +95,9 @@ HostInfoPosix::LookupGroupName(uint32_t gid, std::string &group_name) } } group_name.clear(); +#else + assert(false && "getgrgid_r() not supported on Android"); +#endif return NULL; } @@ -121,6 +125,12 @@ HostInfoPosix::GetEffectiveGroupID() return getegid(); } +FileSpec +HostInfoPosix::GetDefaultShell() +{ + return FileSpec("/bin/sh", false); +} + bool HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec) { @@ -173,6 +183,7 @@ HostInfoPosix::ComputeHeaderDirectory(FileSpec &file_spec) bool HostInfoPosix::ComputePythonDirectory(FileSpec &file_spec) { +#ifndef LLDB_DISABLE_PYTHON FileSpec lldb_file_spec; if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) return false; @@ -190,4 +201,7 @@ HostInfoPosix::ComputePythonDirectory(FileSpec &file_spec) file_spec.GetDirectory().SetCString(raw_path); return true; +#else + return false; +#endif } diff --git a/source/Host/posix/HostProcessPosix.cpp b/source/Host/posix/HostProcessPosix.cpp index 4618de4711de..8e19add048ee 100644 --- a/source/Host/posix/HostProcessPosix.cpp +++ b/source/Host/posix/HostProcessPosix.cpp @@ -1,4 +1,4 @@ -//===-- HostProcessWindows.cpp ----------------------------------*- C++ -*-===// +//===-- HostProcessPosix.cpp ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/Host.h" #include "lldb/Host/posix/HostProcessPosix.h" #include "lldb/Host/FileSystem.h" @@ -16,49 +17,52 @@ using namespace lldb_private; -const lldb::pid_t HostProcessPosix::kInvalidProcessId = 0; +namespace +{ + const int kInvalidPosixProcess = 0; +} HostProcessPosix::HostProcessPosix() -: m_pid(kInvalidProcessId) + : HostNativeProcessBase(kInvalidPosixProcess) { } -HostProcessPosix::~HostProcessPosix() +HostProcessPosix::HostProcessPosix(lldb::process_t process) + : HostNativeProcessBase(process) { } -Error HostProcessPosix::Create(lldb::pid_t pid) +HostProcessPosix::~HostProcessPosix() { - Error error; - if (pid == kInvalidProcessId) - error.SetErrorString("Attempt to create an invalid process"); - - m_pid = pid; - return error; } Error HostProcessPosix::Signal(int signo) const { - if (m_pid <= 0) + if (m_process == kInvalidPosixProcess) { Error error; error.SetErrorString("HostProcessPosix refers to an invalid process"); return error; } - return HostProcessPosix::Signal(m_pid, signo); + return HostProcessPosix::Signal(m_process, signo); } -Error HostProcessPosix::Signal(lldb::pid_t pid, int signo) +Error HostProcessPosix::Signal(lldb::process_t process, int signo) { Error error; - if (-1 == ::kill(pid, signo)) + if (-1 == ::kill(process, signo)) error.SetErrorToErrno(); return error; } +Error HostProcessPosix::Terminate() +{ + return Signal(SIGKILL); +} + Error HostProcessPosix::GetMainModule(FileSpec &file_spec) const { Error error; @@ -66,7 +70,7 @@ Error HostProcessPosix::GetMainModule(FileSpec &file_spec) const // Use special code here because proc/[pid]/exe is a symbolic link. char link_path[PATH_MAX]; char exe_path[PATH_MAX] = ""; - if (snprintf (link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", m_pid) <= 0) + if (snprintf (link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", m_process) <= 0) { error.SetErrorString("Unable to build /proc//exe string"); return error; @@ -92,12 +96,21 @@ Error HostProcessPosix::GetMainModule(FileSpec &file_spec) const lldb::pid_t HostProcessPosix::GetProcessId() const { - return m_pid; + return m_process; } bool HostProcessPosix::IsRunning() const { + if (m_process == kInvalidPosixProcess) + return false; + // Send this process the null signal. If it succeeds the process is running. Error error = Signal(0); return error.Success(); } + +HostThread +HostProcessPosix::StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals) +{ + return Host::StartMonitoringChildProcess(callback, callback_baton, m_process, monitor_signals); +} diff --git a/source/Host/posix/HostThreadPosix.cpp b/source/Host/posix/HostThreadPosix.cpp new file mode 100644 index 000000000000..9c4892431938 --- /dev/null +++ b/source/Host/posix/HostThreadPosix.cpp @@ -0,0 +1,74 @@ +//===-- HostThreadPosix.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Error.h" +#include "lldb/Host/posix/HostThreadPosix.h" + +#include +#include + +using namespace lldb; +using namespace lldb_private; + +HostThreadPosix::HostThreadPosix() +{ +} + +HostThreadPosix::HostThreadPosix(lldb::thread_t thread) + : HostNativeThreadBase(thread) +{ +} + +HostThreadPosix::~HostThreadPosix() +{ +} + +Error +HostThreadPosix::Join(lldb::thread_result_t *result) +{ + Error error; + if (IsJoinable()) + { + int err = ::pthread_join(m_thread, result); + error.SetError(err, lldb::eErrorTypePOSIX); + } + else + { + if (result) + *result = NULL; + error.SetError(EINVAL, eErrorTypePOSIX); + } + + Reset(); + return error; +} + +Error +HostThreadPosix::Cancel() +{ + Error error; +#ifndef __ANDROID__ + int err = ::pthread_cancel(m_thread); + error.SetError(err, eErrorTypePOSIX); +#else + error.SetErrorString("HostThreadPosix::Cancel() not supported on Android"); +#endif + + return error; +} + +Error +HostThreadPosix::Detach() +{ + Error error; + int err = ::pthread_detach(m_thread); + error.SetError(err, eErrorTypePOSIX); + Reset(); + return error; +} diff --git a/source/Host/posix/PipePosix.cpp b/source/Host/posix/PipePosix.cpp new file mode 100644 index 000000000000..02838ec5124e --- /dev/null +++ b/source/Host/posix/PipePosix.cpp @@ -0,0 +1,378 @@ +//===-- PipePosix.cpp -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/posix/PipePosix.h" +#include "lldb/Host/FileSystem.h" + +#include +#include + +#include +#include +#include +#include +#include + +using namespace lldb; +using namespace lldb_private; + +int PipePosix::kInvalidDescriptor = -1; + +enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE + +// pipe2 is supported by Linux, FreeBSD v10 and higher. +// TODO: Add more platforms that support pipe2. +#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) +#define PIPE2_SUPPORTED 1 +#else +#define PIPE2_SUPPORTED 0 +#endif + +namespace +{ + +constexpr auto OPEN_WRITER_SLEEP_TIMEOUT_MSECS = 100; + +#if defined(FD_CLOEXEC) && !PIPE2_SUPPORTED +bool SetCloexecFlag(int fd) +{ + int flags = ::fcntl(fd, F_GETFD); + if (flags == -1) + return false; + return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0); +} +#endif + +std::chrono::time_point +Now() +{ + return std::chrono::steady_clock::now(); +} + +Error +SelectIO(int handle, bool is_read, const std::function &io_handler, const std::chrono::microseconds &timeout) +{ + Error error; + fd_set fds; + bool done = false; + + using namespace std::chrono; + + const auto finish_time = Now() + timeout; + + while (!done) + { + struct timeval tv = {0, 0}; + if (timeout != microseconds::zero()) + { + const auto remaining_dur = duration_cast(finish_time - Now()); + if (remaining_dur.count() <= 0) + { + error.SetErrorString("timeout exceeded"); + break; + } + const auto dur_secs = duration_cast(remaining_dur); + const auto dur_usecs = remaining_dur % seconds(1); + + tv.tv_sec = dur_secs.count(); + tv.tv_usec = dur_usecs.count(); + } + else + tv.tv_sec = 1; + + FD_ZERO(&fds); + FD_SET(handle, &fds); + + const auto retval = ::select(handle + 1, + (is_read) ? &fds : nullptr, + (is_read) ? nullptr : &fds, + nullptr, &tv); + if (retval == -1) + { + if (errno == EINTR) + continue; + error.SetErrorToErrno(); + break; + } + if (retval == 0) + { + error.SetErrorString("timeout exceeded"); + break; + } + if (!FD_ISSET(handle, &fds)) + { + error.SetErrorString("invalid state"); + break; + } + + error = io_handler(done); + if (error.Fail()) + { + if (error.GetError() == EINTR) + continue; + break; + } + } + return error; +} + +} + +PipePosix::PipePosix() +{ + m_fds[READ] = PipePosix::kInvalidDescriptor; + m_fds[WRITE] = PipePosix::kInvalidDescriptor; +} + +PipePosix::~PipePosix() +{ + Close(); +} + +Error +PipePosix::CreateNew(bool child_processes_inherit) +{ + if (CanRead() || CanWrite()) + return Error(EINVAL, eErrorTypePOSIX); + + Error error; +#if PIPE2_SUPPORTED + if (::pipe2(m_fds, (child_processes_inherit) ? 0 : O_CLOEXEC) == 0) + return error; +#else + if (::pipe(m_fds) == 0) + { +#ifdef FD_CLOEXEC + if (!child_processes_inherit) + { + if (!SetCloexecFlag(m_fds[0]) || !SetCloexecFlag(m_fds[1])) + { + error.SetErrorToErrno(); + Close(); + return error; + } + } +#endif + return error; + } +#endif + + error.SetErrorToErrno(); + m_fds[READ] = PipePosix::kInvalidDescriptor; + m_fds[WRITE] = PipePosix::kInvalidDescriptor; + return error; +} + +Error +PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit) +{ + if (CanRead() || CanWrite()) + return Error("Pipe is already opened"); + + Error error; + if (::mkfifo(name.data(), 0660) != 0) + error.SetErrorToErrno(); + + return error; +} + +Error +PipePosix::OpenAsReader(llvm::StringRef name, bool child_process_inherit) +{ + if (CanRead() || CanWrite()) + return Error("Pipe is already opened"); + + int flags = O_RDONLY | O_NONBLOCK; + if (!child_process_inherit) + flags |= O_CLOEXEC; + + Error error; + int fd = ::open(name.data(), flags); + if (fd != -1) + m_fds[READ] = fd; + else + error.SetErrorToErrno(); + + return error; +} + +Error +PipePosix::OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) +{ + if (CanRead() || CanWrite()) + return Error("Pipe is already opened"); + + int flags = O_WRONLY | O_NONBLOCK; + if (!child_process_inherit) + flags |= O_CLOEXEC; + + using namespace std::chrono; + const auto finish_time = Now() + timeout; + + while (!CanWrite()) + { + if (timeout != microseconds::zero()) + { + const auto dur = duration_cast(finish_time - Now()).count(); + if (dur <= 0) + return Error("timeout exceeded - reader hasn't opened so far"); + } + + errno = 0; + int fd = ::open(name.data(), flags); + if (fd == -1) + { + const auto errno_copy = errno; + // We may get ENXIO if a reader side of the pipe hasn't opened yet. + if (errno_copy != ENXIO) + return Error(errno_copy, eErrorTypePOSIX); + + std::this_thread::sleep_for(milliseconds(OPEN_WRITER_SLEEP_TIMEOUT_MSECS)); + } + else + { + m_fds[WRITE] = fd; + } + } + + return Error(); +} + +int +PipePosix::GetReadFileDescriptor() const +{ + return m_fds[READ]; +} + +int +PipePosix::GetWriteFileDescriptor() const +{ + return m_fds[WRITE]; +} + +int +PipePosix::ReleaseReadFileDescriptor() +{ + const int fd = m_fds[READ]; + m_fds[READ] = PipePosix::kInvalidDescriptor; + return fd; +} + +int +PipePosix::ReleaseWriteFileDescriptor() +{ + const int fd = m_fds[WRITE]; + m_fds[WRITE] = PipePosix::kInvalidDescriptor; + return fd; +} + +void +PipePosix::Close() +{ + CloseReadFileDescriptor(); + CloseWriteFileDescriptor(); +} + +Error +PipePosix::Delete(llvm::StringRef name) +{ + return FileSystem::Unlink(name.data()); +} + +bool +PipePosix::CanRead() const +{ + return m_fds[READ] != PipePosix::kInvalidDescriptor; +} + +bool +PipePosix::CanWrite() const +{ + return m_fds[WRITE] != PipePosix::kInvalidDescriptor; +} + +void +PipePosix::CloseReadFileDescriptor() +{ + if (CanRead()) + { + close(m_fds[READ]); + m_fds[READ] = PipePosix::kInvalidDescriptor; + } +} + +void +PipePosix::CloseWriteFileDescriptor() +{ + if (CanWrite()) + { + close(m_fds[WRITE]); + m_fds[WRITE] = PipePosix::kInvalidDescriptor; + } +} + +Error +PipePosix::ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read) +{ + bytes_read = 0; + if (!CanRead()) + return Error(EINVAL, eErrorTypePOSIX); + + auto handle = GetReadFileDescriptor(); + return SelectIO(handle, + true, + [=, &bytes_read](bool &done) + { + Error error; + auto result = ::read(handle, + reinterpret_cast(buf) + bytes_read, + size - bytes_read); + if (result != -1) + { + bytes_read += result; + if (bytes_read == size || result == 0) + done = true; + } + else + error.SetErrorToErrno(); + + return error; + }, + timeout); +} + +Error +PipePosix::Write(const void *buf, size_t size, size_t &bytes_written) +{ + bytes_written = 0; + if (!CanWrite()) + return Error(EINVAL, eErrorTypePOSIX); + + auto handle = GetWriteFileDescriptor(); + return SelectIO(handle, + false, + [=, &bytes_written](bool &done) + { + Error error; + auto result = ::write(handle, + reinterpret_cast(buf) + bytes_written, + size - bytes_written); + if (result != -1) + { + bytes_written += result; + if (bytes_written == size) + done = true; + } + else + error.SetErrorToErrno(); + + return error; + }, + std::chrono::microseconds::zero()); +} diff --git a/source/Host/posix/ProcessLauncherPosix.cpp b/source/Host/posix/ProcessLauncherPosix.cpp new file mode 100644 index 000000000000..dd5c5121a97b --- /dev/null +++ b/source/Host/posix/ProcessLauncherPosix.cpp @@ -0,0 +1,33 @@ +//===-- ProcessLauncherPosix.cpp --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Host.h" +#include "lldb/Host/HostProcess.h" +#include "lldb/Host/posix/ProcessLauncherPosix.h" + +#include "lldb/Target/ProcessLaunchInfo.h" + +#include + +using namespace lldb; +using namespace lldb_private; + +HostProcess +ProcessLauncherPosix::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) +{ + lldb::pid_t pid; + char exe_path[PATH_MAX]; + + launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); + + // TODO(zturner): Move the code from LaunchProcessPosixSpawn to here, and make MacOSX re-use this + // ProcessLauncher when it wants a posix_spawn launch. + error = Host::LaunchProcessPosixSpawn(exe_path, launch_info, pid); + return HostProcess(pid); +} diff --git a/source/Interpreter/Args.cpp b/source/Interpreter/Args.cpp index 4831eaaac348..93933802f57c 100644 --- a/source/Interpreter/Args.cpp +++ b/source/Interpreter/Args.cpp @@ -685,7 +685,7 @@ Args::ParseOptions (Options &options) } } // Call the callback with the option - if (long_options_index >= 0) + if (long_options_index >= 0 && long_options[long_options_index].definition) { const OptionDefinition *def = long_options[long_options_index].definition; CommandInterpreter &interpreter = options.GetInterpreter(); @@ -829,15 +829,18 @@ Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::add options.SetTryAllThreads(true); ExpressionResults expr_result = target->EvaluateExpression(s, - exe_ctx->GetFramePtr(), - valobj_sp, - options); + exe_ctx->GetFramePtr(), + valobj_sp, + options); bool success = false; if (expr_result == eExpressionCompleted) { + if (valobj_sp) + valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable(valobj_sp->GetDynamicValueType(), true); // Get the address to watch. - addr = valobj_sp->GetValueAsUnsigned(fail_value, &success); + if (valobj_sp) + addr = valobj_sp->GetValueAsUnsigned(fail_value, &success); if (success) { if (error_ptr) @@ -966,6 +969,26 @@ Args::StringToBoolean (const char *s, bool fail_value, bool *success_ptr) return fail_value; } +char +Args::StringToChar(const char *s, char fail_value, bool *success_ptr) +{ + bool success = false; + char result = fail_value; + + if (s) + { + size_t length = strlen(s); + if (length == 1) + { + success = true; + result = s[0]; + } + } + if (success_ptr) + *success_ptr = success; + return result; +} + const char * Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t &update) { diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp index 56c8f8c0ad6a..176a1fc9a3b0 100644 --- a/source/Interpreter/CommandInterpreter.cpp +++ b/source/Interpreter/CommandInterpreter.cpp @@ -49,7 +49,9 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/Timer.h" +#ifndef LLDB_DISABLE_LIBEDIT #include "lldb/Host/Editline.h" +#endif #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" @@ -117,7 +119,11 @@ CommandInterpreter::CommandInterpreter m_comment_char ('#'), m_batch_command_mode (false), m_truncation_warning(eNoTruncation), - m_command_source_depth (0) + m_command_source_depth (0), + m_num_errors(0), + m_quit_requested(false), + m_stopped_for_crash(false) + { debugger.SetScriptLanguage (script_language); SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit"); @@ -333,7 +339,11 @@ CommandInterpreter::Initialize () #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp); #else - ProcessAliasOptionsArgs (cmd_obj_sp, "--shell=" LLDB_DEFAULT_SHELL " --", alias_arguments_vector_sp); + std::string shell_option; + shell_option.append("--shell="); + shell_option.append(HostInfo::GetDefaultShell().GetPath()); + shell_option.append(" --"); + ProcessAliasOptionsArgs (cmd_obj_sp, shell_option.c_str(), alias_arguments_vector_sp); #endif AddAlias ("r", cmd_obj_sp); AddAlias ("run", cmd_obj_sp); @@ -414,6 +424,7 @@ CommandInterpreter::LoadCommandDictionary () m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this)); const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"}, + {"^/([^/]+)/$", "breakpoint set --source-pattern-regexp '%1'"}, {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"}, {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"}, {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}, @@ -431,7 +442,8 @@ CommandInterpreter::LoadCommandDictionary () "_regexp-break [:]\n_regexp-break []\n_regexp-break [
]\n_regexp-break <...>", 2, CommandCompletions::eSymbolCompletion | - CommandCompletions::eSourceFileCompletion)); + CommandCompletions::eSourceFileCompletion, + false)); if (break_regex_cmd_ap.get()) { @@ -458,7 +470,8 @@ CommandInterpreter::LoadCommandDictionary () "_regexp-tbreak [:]\n_regexp-break []\n_regexp-break [
]\n_regexp-break <...>", 2, CommandCompletions::eSymbolCompletion | - CommandCompletions::eSourceFileCompletion)); + CommandCompletions::eSourceFileCompletion, + false)); if (tbreak_regex_cmd_ap.get()) { @@ -469,6 +482,8 @@ CommandInterpreter::LoadCommandDictionary () char buffer[1024]; int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o"); assert (num_printed < 1024); + // Quiet unused variable warning for release builds. + (void) num_printed; success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer); if (!success) break; @@ -487,7 +502,9 @@ CommandInterpreter::LoadCommandDictionary () "_regexp-attach", "Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.", "_regexp-attach []\n_regexp-attach []", - 2)); + 2, + 0, + false)); if (attach_regex_cmd_ap.get()) { if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") && @@ -504,7 +521,10 @@ CommandInterpreter::LoadCommandDictionary () down_regex_cmd_ap(new CommandObjectRegexCommand (*this, "_regexp-down", "Go down \"n\" frames in the stack (1 frame by default).", - "_regexp-down [n]", 2)); + "_regexp-down [n]", + 2, + 0, + false)); if (down_regex_cmd_ap.get()) { if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") && @@ -519,7 +539,10 @@ CommandInterpreter::LoadCommandDictionary () up_regex_cmd_ap(new CommandObjectRegexCommand (*this, "_regexp-up", "Go up \"n\" frames in the stack (1 frame by default).", - "_regexp-up [n]", 2)); + "_regexp-up [n]", + 2, + 0, + false)); if (up_regex_cmd_ap.get()) { if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") && @@ -534,7 +557,10 @@ CommandInterpreter::LoadCommandDictionary () display_regex_cmd_ap(new CommandObjectRegexCommand (*this, "_regexp-display", "Add an expression evaluation stop-hook.", - "_regexp-display expression", 2)); + "_regexp-display expression", + 2, + 0, + false)); if (display_regex_cmd_ap.get()) { if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\"")) @@ -548,7 +574,10 @@ CommandInterpreter::LoadCommandDictionary () undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this, "_regexp-undisplay", "Remove an expression evaluation stop-hook.", - "_regexp-undisplay stop-hook-number", 2)); + "_regexp-undisplay stop-hook-number", + 2, + 0, + false)); if (undisplay_regex_cmd_ap.get()) { if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1")) @@ -562,7 +591,10 @@ CommandInterpreter::LoadCommandDictionary () connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this, "gdb-remote", "Connect to a remote GDB server. If no hostname is provided, localhost is assumed.", - "gdb-remote [:]", 2)); + "gdb-remote [:]", + 2, + 0, + false)); if (connect_gdb_remote_cmd_ap.get()) { if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") && @@ -577,7 +609,10 @@ CommandInterpreter::LoadCommandDictionary () connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this, "kdp-remote", "Connect to a remote KDP server. udp port 41139 is the default port number.", - "kdp-remote [:]", 2)); + "kdp-remote [:]", + 2, + 0, + false)); if (connect_kdp_remote_cmd_ap.get()) { if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") && @@ -590,9 +625,12 @@ CommandInterpreter::LoadCommandDictionary () std::unique_ptr bt_regex_cmd_ap(new CommandObjectRegexCommand (*this, - "_regexp-bt", - "Show a backtrace. An optional argument is accepted; if that argument is a number, it specifies the number of frames to display. If that argument is 'all', full backtraces of all threads are displayed.", - "bt [|all]", 2)); + "_regexp-bt", + "Show a backtrace. An optional argument is accepted; if that argument is a number, it specifies the number of frames to display. If that argument is 'all', full backtraces of all threads are displayed.", + "bt [|all]", + 2, + 0, + false)); if (bt_regex_cmd_ap.get()) { // accept but don't document "bt -c " -- before bt was a regex command if you wanted to backtrace @@ -614,7 +652,8 @@ CommandInterpreter::LoadCommandDictionary () "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.", "_regexp-list []\n_regexp-list [:]\n_regexp-list [:]", 2, - CommandCompletions::eSourceFileCompletion)); + CommandCompletions::eSourceFileCompletion, + false)); if (list_regex_cmd_ap.get()) { if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") && @@ -634,7 +673,10 @@ CommandInterpreter::LoadCommandDictionary () env_regex_cmd_ap(new CommandObjectRegexCommand (*this, "_regexp-env", "Implements a shortcut to viewing and setting environment variables.", - "_regexp-env\n_regexp-env FOO=BAR", 2)); + "_regexp-env\n_regexp-env FOO=BAR", + 2, + 0, + false)); if (env_regex_cmd_ap.get()) { if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") && @@ -652,7 +694,10 @@ CommandInterpreter::LoadCommandDictionary () "_regexp-jump []\n" "_regexp-jump [<+-lineoffset>]\n" "_regexp-jump [:]\n" - "_regexp-jump [*]\n", 2)); + "_regexp-jump [*]\n", + 2, + 0, + false)); if (jump_regex_cmd_ap.get()) { if (jump_regex_cmd_ap->AddRegexCommand("^\\*(.*)$", "thread jump --addr %1") && @@ -1043,6 +1088,22 @@ CommandInterpreter::RemoveAlias (const char *alias_name) } return false; } + +bool +CommandInterpreter::RemoveCommand (const char *cmd) +{ + auto pos = m_command_dict.find(cmd); + if (pos != m_command_dict.end()) + { + if (pos->second->IsRemovable()) + { + // Only regular expression objects or python commands are removable + m_command_dict.erase(pos); + return true; + } + } + return false; +} bool CommandInterpreter::RemoveUser (const char *alias_name) { @@ -1448,7 +1509,7 @@ CommandInterpreter::PreprocessCommand (std::string &command) // Get a dummy target to allow for calculator mode while processing backticks. // This also helps break the infinite loop caused when target is null. if (!target) - target = Host::GetDummyTarget(GetDebugger()).get(); + target = m_debugger.GetDummyTarget(); if (target) { ValueObjectSP expr_result_valobj_sp; @@ -1462,13 +1523,15 @@ CommandInterpreter::PreprocessCommand (std::string &command) options.SetTimeoutUsec(0); ExpressionResults expr_result = target->EvaluateExpression (expr_str.c_str(), - exe_ctx.GetFramePtr(), - expr_result_valobj_sp, - options); + exe_ctx.GetFramePtr(), + expr_result_valobj_sp, + options); if (expr_result == eExpressionCompleted) { Scalar scalar; + if (expr_result_valobj_sp) + expr_result_valobj_sp = expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(expr_result_valobj_sp->GetDynamicValueType(), true); if (expr_result_valobj_sp->ResolveValue (scalar)) { command.erase (start_backtick, end_backtick - start_backtick + 1); @@ -2415,13 +2478,14 @@ CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result) if (init_file.Exists()) { const bool saved_batch = SetBatchCommandMode (true); + CommandInterpreterRunOptions options; + options.SetSilent (true); + options.SetStopOnError (false); + options.SetStopOnContinue (true); + HandleCommandsFromFile (init_file, nullptr, // Execution context - eLazyBoolYes, // Stop on continue - eLazyBoolNo, // Stop on error - eLazyBoolNo, // Don't echo commands - eLazyBoolNo, // Don't print command output - eLazyBoolNo, // Don't add the commands that are sourced into the history buffer + options, result); SetBatchCommandMode (saved_batch); } @@ -2451,12 +2515,8 @@ CommandInterpreter::GetPlatform (bool prefer_target_platform) void CommandInterpreter::HandleCommands (const StringList &commands, - ExecutionContext *override_context, - bool stop_on_continue, - bool stop_on_error, - bool echo_commands, - bool print_results, - LazyBool add_to_history, + ExecutionContext *override_context, + CommandInterpreterRunOptions &options, CommandReturnObject &result) { size_t num_lines = commands.GetSize(); @@ -2472,7 +2532,7 @@ CommandInterpreter::HandleCommands (const StringList &commands, if (override_context != nullptr) UpdateExecutionContext (override_context); - if (!stop_on_continue) + if (!options.GetStopOnContinue()) { m_debugger.SetAsyncExecution (false); } @@ -2483,7 +2543,7 @@ CommandInterpreter::HandleCommands (const StringList &commands, if (cmd[0] == '\0') continue; - if (echo_commands) + if (options.GetEchoCommands()) { result.AppendMessageWithFormat ("%s %s\n", m_debugger.GetPrompt(), @@ -2496,16 +2556,16 @@ CommandInterpreter::HandleCommands (const StringList &commands, // 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 (!add_to_history) + if (!options.GetAddToHistory()) m_command_source_depth++; - bool success = HandleCommand(cmd, add_to_history, tmp_result, + 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 */); - if (!add_to_history) + if (!options.GetAddToHistory()) m_command_source_depth--; - if (print_results) + if (options.GetPrintResults()) { if (tmp_result.Succeeded()) result.AppendMessageWithFormat("%s", tmp_result.GetOutputData()); @@ -2516,7 +2576,7 @@ CommandInterpreter::HandleCommands (const StringList &commands, const char *error_msg = tmp_result.GetErrorData(); if (error_msg == nullptr || error_msg[0] == '\0') error_msg = ".\n"; - if (stop_on_error) + if (options.GetStopOnError()) { result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' failed with %s", (uint64_t)idx, cmd, error_msg); @@ -2524,7 +2584,7 @@ CommandInterpreter::HandleCommands (const StringList &commands, m_debugger.SetAsyncExecution (old_async_execution); return; } - else if (print_results) + else if (options.GetPrintResults()) { result.AppendMessageWithFormat ("Command #%" PRIu64 " '%s' failed with %s", (uint64_t)idx + 1, @@ -2545,7 +2605,7 @@ CommandInterpreter::HandleCommands (const StringList &commands, if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult) || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult)) { - if (stop_on_continue) + if (options.GetStopOnContinue()) { // If we caused the target to proceed, and we're going to stop in that case, set the // status in our real result before returning. This is an error if the continue was not the @@ -2562,6 +2622,42 @@ CommandInterpreter::HandleCommands (const StringList &commands, return; } } + + // Also check for "stop on crash here: + bool should_stop = false; + if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash()) + { + TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); + if (target_sp) + { + ProcessSP process_sp (target_sp->GetProcessSP()); + if (process_sp) + { + for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) + { + StopReason reason = thread_sp->GetStopReason(); + if (reason == eStopReasonSignal || reason == eStopReasonException || reason == eStopReasonInstrumentation) + { + should_stop = true; + break; + } + } + } + } + if (should_stop) + { + if (idx != num_lines - 1) + result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' stopped with a signal or exception.\n", + (uint64_t)idx + 1, cmd); + else + result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' stopped with a signal or exception.\n", (uint64_t)idx + 1, cmd); + + result.SetStatus(tmp_result.GetStatus()); + m_debugger.SetAsyncExecution (old_async_execution); + + return; + } + } } @@ -2576,17 +2672,14 @@ enum { eHandleCommandFlagStopOnContinue = (1u << 0), eHandleCommandFlagStopOnError = (1u << 1), eHandleCommandFlagEchoCommand = (1u << 2), - eHandleCommandFlagPrintResult = (1u << 3) + eHandleCommandFlagPrintResult = (1u << 3), + eHandleCommandFlagStopOnCrash = (1u << 4) }; void CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, ExecutionContext *context, - LazyBool stop_on_continue, - LazyBool stop_on_error, - LazyBool echo_command, - LazyBool print_result, - LazyBool add_to_history, + CommandInterpreterRunOptions &options, CommandReturnObject &result) { if (cmd_file.Exists()) @@ -2602,7 +2695,7 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, uint32_t flags = 0; - if (stop_on_continue == eLazyBoolCalculate) + if (options.m_stop_on_continue == eLazyBoolCalculate) { if (m_command_source_flags.empty()) { @@ -2614,12 +2707,12 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, flags |= eHandleCommandFlagStopOnContinue; } } - else if (stop_on_continue == eLazyBoolYes) + else if (options.m_stop_on_continue == eLazyBoolYes) { flags |= eHandleCommandFlagStopOnContinue; } - if (stop_on_error == eLazyBoolCalculate) + if (options.m_stop_on_error == eLazyBoolCalculate) { if (m_command_source_flags.empty()) { @@ -2631,12 +2724,25 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, flags |= eHandleCommandFlagStopOnError; } } - else if (stop_on_error == eLazyBoolYes) + else if (options.m_stop_on_error == eLazyBoolYes) { flags |= eHandleCommandFlagStopOnError; } - if (echo_command == eLazyBoolCalculate) + if (options.GetStopOnCrash()) + { + if (m_command_source_flags.empty()) + { + // Echo command by default + flags |= eHandleCommandFlagStopOnCrash; + } + else if (m_command_source_flags.back() & eHandleCommandFlagStopOnCrash) + { + flags |= eHandleCommandFlagStopOnCrash; + } + } + + if (options.m_echo_commands == eLazyBoolCalculate) { if (m_command_source_flags.empty()) { @@ -2648,12 +2754,12 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, flags |= eHandleCommandFlagEchoCommand; } } - else if (echo_command == eLazyBoolYes) + else if (options.m_echo_commands == eLazyBoolYes) { flags |= eHandleCommandFlagEchoCommand; } - if (print_result == eLazyBoolCalculate) + if (options.m_print_results == eLazyBoolCalculate) { if (m_command_source_flags.empty()) { @@ -2665,7 +2771,7 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, flags |= eHandleCommandFlagPrintResult; } } - else if (print_result == eLazyBoolYes) + else if (options.m_print_results == eLazyBoolYes) { flags |= eHandleCommandFlagPrintResult; } @@ -2680,18 +2786,21 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, lldb::StreamFileSP empty_stream_sp; m_command_source_flags.push_back(flags); IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, + IOHandler::Type::CommandInterpreter, input_file_sp, empty_stream_sp, // Pass in an empty stream so we inherit the top input reader output stream empty_stream_sp, // Pass in an empty stream so we inherit the top input reader error stream flags, nullptr, // Pass in NULL for "editline_name" so no history is saved, or written debugger.GetPrompt(), + NULL, false, // Not multi-line + debugger.GetUseColor(), 0, *this)); const bool old_async_execution = debugger.GetAsyncExecution(); - // Set synchronous execution if we not stopping when we continue + // Set synchronous execution if we are not stopping on continue if ((flags & eHandleCommandFlagStopOnContinue) == 0) debugger.SetAsyncExecution (false); @@ -2715,7 +2824,7 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, else { result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n", - cmd_file.GetFilename().AsCString()); + cmd_file.GetFilename().AsCString("")); result.SetStatus (eReturnStatusFailed); return; } @@ -3056,14 +3165,46 @@ CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string & break; case eReturnStatusFailed: + m_num_errors++; if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError)) io_handler.SetIsDone(true); break; case eReturnStatusQuit: + m_quit_requested = true; io_handler.SetIsDone(true); break; } + + // Finally, if we're going to stop on crash, check that here: + if (!m_quit_requested + && result.GetDidChangeProcessState() + && io_handler.GetFlags().Test(eHandleCommandFlagStopOnCrash)) + { + bool should_stop = false; + TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); + if (target_sp) + { + ProcessSP process_sp (target_sp->GetProcessSP()); + if (process_sp) + { + for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) + { + StopReason reason = thread_sp->GetStopReason(); + if (reason == eStopReasonSignal || reason == eStopReasonException || reason == eStopReasonInstrumentation) + { + should_stop = true; + break; + } + } + } + } + if (should_stop) + { + io_handler.SetIsDone(true); + m_stopped_for_crash = true; + } + } } bool @@ -3092,9 +3233,12 @@ CommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt, { Debugger &debugger = GetDebugger(); IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, + IOHandler::Type::CommandList, "lldb", // Name of input reader for history prompt, // Prompt + NULL, // Continuation prompt true, // Get multiple lines + debugger.GetUseColor(), 0, // Don't show line numbers delegate)); // IOHandlerDelegate @@ -3118,9 +3262,12 @@ CommandInterpreter::GetPythonCommandsFromIOHandler (const char *prompt, { Debugger &debugger = GetDebugger(); IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, + IOHandler::Type::PythonCode, "lldb-python", // Name of input reader for history prompt, // Prompt + NULL, // Continuation prompt true, // Get multiple lines + debugger.GetUseColor(), 0, // Don't show line numbers delegate)); // IOHandlerDelegate @@ -3141,28 +3288,64 @@ CommandInterpreter::IsActive () return m_debugger.IsTopIOHandler (m_command_io_handler_sp); } -void -CommandInterpreter::RunCommandInterpreter(bool auto_handle_events, - bool spawn_thread) +lldb::IOHandlerSP +CommandInterpreter::GetIOHandler(bool force_create, CommandInterpreterRunOptions *options) { - // Only get one line at a time - const bool multiple_lines = false; - // Always re-create the IOHandlerEditline in case the input // changed. The old instance might have had a non-interactive // input and now it does or vice versa. - m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger, - m_debugger.GetInputFile(), - m_debugger.GetOutputFile(), - m_debugger.GetErrorFile(), - eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult, - "lldb", - m_debugger.GetPrompt(), - multiple_lines, - 0, // Don't show line numbers - *this)); - - m_debugger.PushIOHandler(m_command_io_handler_sp); + if (force_create || !m_command_io_handler_sp) + { + // Always re-create the IOHandlerEditline in case the input + // changed. The old instance might have had a non-interactive + // input and now it does or vice versa. + uint32_t flags = 0; + + if (options) + { + if (options->m_stop_on_continue == eLazyBoolYes) + flags |= eHandleCommandFlagStopOnContinue; + if (options->m_stop_on_error == eLazyBoolYes) + flags |= eHandleCommandFlagStopOnError; + if (options->m_stop_on_crash == eLazyBoolYes) + flags |= eHandleCommandFlagStopOnCrash; + if (options->m_echo_commands != eLazyBoolNo) + flags |= eHandleCommandFlagEchoCommand; + if (options->m_print_results != eLazyBoolNo) + flags |= eHandleCommandFlagPrintResult; + } + else + { + flags = eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult; + } + + m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger, + IOHandler::Type::CommandInterpreter, + m_debugger.GetInputFile(), + m_debugger.GetOutputFile(), + m_debugger.GetErrorFile(), + flags, + "lldb", + m_debugger.GetPrompt(), + NULL, // Continuation prompt + false, // Don't enable multiple line input, just single line commands + m_debugger.GetUseColor(), + 0, // Don't show line numbers + *this)); + } + return m_command_io_handler_sp; +} + +void +CommandInterpreter::RunCommandInterpreter(bool auto_handle_events, + bool spawn_thread, + CommandInterpreterRunOptions &options) +{ + // Always re-create the command intepreter when we run it in case + // any file handles have changed. + bool force_create = true; + m_debugger.PushIOHandler(GetIOHandler(force_create, &options)); + m_stopped_for_crash = false; if (auto_handle_events) m_debugger.StartEventHandlerThread(); @@ -3174,10 +3357,10 @@ CommandInterpreter::RunCommandInterpreter(bool auto_handle_events, else { m_debugger.ExecuteIOHanders(); - + if (auto_handle_events) m_debugger.StopEventHandlerThread(); } - + } diff --git a/source/Interpreter/CommandObject.cpp b/source/Interpreter/CommandObject.cpp index 3fdbf994fe7a..753e720b0f6e 100644 --- a/source/Interpreter/CommandObject.cpp +++ b/source/Interpreter/CommandObject.cpp @@ -49,7 +49,7 @@ CommandObject::CommandObject uint32_t flags ) : m_interpreter (interpreter), - m_cmd_name (name), + m_cmd_name (name ? name : ""), m_cmd_help_short (), m_cmd_help_long (), m_cmd_syntax (), @@ -236,19 +236,34 @@ CommandObject::CheckRequirements (CommandReturnObject &result) if ((flags & eFlagRequiresProcess) && !m_exe_ctx.HasProcessScope()) { - result.AppendError (GetInvalidProcessDescription()); + if (!m_exe_ctx.HasTargetScope()) + result.AppendError (GetInvalidTargetDescription()); + else + result.AppendError (GetInvalidProcessDescription()); return false; } if ((flags & eFlagRequiresThread) && !m_exe_ctx.HasThreadScope()) { - result.AppendError (GetInvalidThreadDescription()); + if (!m_exe_ctx.HasTargetScope()) + result.AppendError (GetInvalidTargetDescription()); + else if (!m_exe_ctx.HasProcessScope()) + result.AppendError (GetInvalidProcessDescription()); + else + result.AppendError (GetInvalidThreadDescription()); return false; } if ((flags & eFlagRequiresFrame) && !m_exe_ctx.HasFrameScope()) { - result.AppendError (GetInvalidFrameDescription()); + if (!m_exe_ctx.HasTargetScope()) + result.AppendError (GetInvalidTargetDescription()); + else if (!m_exe_ctx.HasProcessScope()) + result.AppendError (GetInvalidProcessDescription()); + else if (!m_exe_ctx.HasThreadScope()) + result.AppendError (GetInvalidThreadDescription()); + else + result.AppendError (GetInvalidFrameDescription()); return false; } @@ -732,6 +747,22 @@ BreakpointIDRangeHelpTextCallback () " is legal; 2 - 5 is legal; but 3.2 - 4.4 is not legal."; } +static const char * +BreakpointNameHelpTextCallback () +{ + return "A name that can be added to a breakpoint when it is created, or later " + "on with the \"breakpoint name add\" command. " + "Breakpoint names can be used to specify breakpoints in all the places breakpoint ID's " + "and breakpoint ID ranges can be used. As such they provide a convenient way to group breakpoints, " + "and to operate on breakpoints you create without having to track the breakpoint number. " + "Note, the attributes you set when using a breakpoint name in a breakpoint command don't " + "adhere to the name, but instead are set individually on all the breakpoints currently tagged with that name. Future breakpoints " + "tagged with that name will not pick up the attributes previously given using that name. " + "In order to distinguish breakpoint names from breakpoint ID's and ranges, " + "names must start with a letter from a-z or A-Z and cannot contain spaces, \".\" or \"-\". " + "Also, breakpoint names can only be applied to breakpoints, not to breakpoint locations."; +} + static const char * GDBFormatHelpTextCallback () { @@ -1003,6 +1034,18 @@ CommandObject::GetArgumentDescriptionAsCString (const lldb::CommandArgumentType return nullptr; } +Target * +CommandObject::GetDummyTarget() +{ + return m_interpreter.GetDebugger().GetDummyTarget(); +} + +Target * +CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy) +{ + return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy); +} + bool CommandObjectParsed::Execute (const char *args_string, CommandReturnObject &result) { @@ -1085,6 +1128,7 @@ CommandObject::g_arguments_data[] = { eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { nullptr, false }, "A Boolean value: 'true' or 'false'" }, { eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, nullptr }, { eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, nullptr }, + { eArgTypeBreakpointName, "breakpoint-name", CommandCompletions::eNoCompletion, { BreakpointNameHelpTextCallback, false }, nullptr }, { eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { nullptr, false }, "Number of bytes to use." }, { eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { nullptr, false }, "Then name of a class from the debug information in the program." }, { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { nullptr, false }, "A debugger command (may be multiple words), without any options or arguments." }, @@ -1103,6 +1147,7 @@ CommandObject::g_arguments_data[] = { eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a function." }, { eArgTypeFunctionOrSymbol, "function-or-symbol", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a function or symbol." }, { eArgTypeGDBFormat, "gdb-format", CommandCompletions::eNoCompletion, { GDBFormatHelpTextCallback, true }, nullptr }, + { eArgTypeHelpText, "help-text", CommandCompletions::eNoCompletion, { nullptr, false }, "Text to be used as help for some other entity in LLDB" }, { eArgTypeIndex, "index", CommandCompletions::eNoCompletion, { nullptr, false }, "An index into a list." }, { eArgTypeLanguage, "language", CommandCompletions::eNoCompletion, { LanguageTypeHelpTextCallback, true }, nullptr }, { eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, { nullptr, false }, "Line number in a source file." }, diff --git a/source/Interpreter/CommandObjectRegexCommand.cpp b/source/Interpreter/CommandObjectRegexCommand.cpp index d27320dd1f3d..efc7c33fa8f6 100644 --- a/source/Interpreter/CommandObjectRegexCommand.cpp +++ b/source/Interpreter/CommandObjectRegexCommand.cpp @@ -31,12 +31,14 @@ CommandObjectRegexCommand::CommandObjectRegexCommand const char *help, const char *syntax, uint32_t max_matches, - uint32_t completion_type_mask + uint32_t completion_type_mask, + bool is_removable ) : CommandObjectRaw (interpreter, name, help, syntax), m_max_matches (max_matches), m_completion_type_mask (completion_type_mask), - m_entries () + m_entries (), + m_is_removable (is_removable) { } diff --git a/source/Interpreter/OptionGroupPlatform.cpp b/source/Interpreter/OptionGroupPlatform.cpp index 9ffd5f072d90..7e5e1245a79f 100644 --- a/source/Interpreter/OptionGroupPlatform.cpp +++ b/source/Interpreter/OptionGroupPlatform.cpp @@ -33,7 +33,7 @@ OptionGroupPlatform::CreatePlatformWithOptions (CommandInterpreter &interpreter, if (!m_platform_name.empty()) { - platform_sp = Platform::Create (m_platform_name.c_str(), error); + platform_sp = Platform::Create (ConstString(m_platform_name.c_str()), error); if (platform_sp) { if (platform_arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) diff --git a/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/source/Interpreter/OptionGroupValueObjectDisplay.cpp index 125e5fb0a5d6..b6c63fa44c40 100644 --- a/source/Interpreter/OptionGroupValueObjectDisplay.cpp +++ b/source/Interpreter/OptionGroupValueObjectDisplay.cpp @@ -45,6 +45,7 @@ g_option_table[] = { LLDB_OPT_SET_1, false, "no-summary-depth", 'Y', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the depth at which omitting summary information stops (default is 1)."}, { LLDB_OPT_SET_1, false, "raw-output", 'R', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use formatting options."}, { LLDB_OPT_SET_1, false, "show-all-children", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Ignore the upper bound on the number of children to show."}, + { LLDB_OPT_SET_1, false, "validate", 'V', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Show results of type validators."}, { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } }; @@ -115,6 +116,13 @@ OptionGroupValueObjectDisplay::SetOptionValue (CommandInterpreter &interpreter, if (!success) error.SetErrorStringWithFormat("invalid synthetic-type '%s'", option_arg); break; + + case 'V': + run_validator = Args::StringToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat("invalid validate '%s'", option_arg); + break; + default: error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); break; @@ -137,6 +145,7 @@ OptionGroupValueObjectDisplay::OptionParsingStarting (CommandInterpreter &interp use_synth = true; be_raw = false; ignore_cap = false; + run_validator = false; Target *target = interpreter.GetExecutionContext().GetTargetPtr(); if (target != nullptr) @@ -176,7 +185,9 @@ OptionGroupValueObjectDisplay::GetAsDumpOptions (LanguageRuntimeDescriptionDispl .SetHideValue(use_objc); if (be_raw) - options.SetRawDisplay(true); + options.SetRawDisplay(); + + options.SetRunValidator(run_validator); return options; } diff --git a/source/Interpreter/OptionValue.cpp b/source/Interpreter/OptionValue.cpp index bc1e1c4c4779..a08a6127db15 100644 --- a/source/Interpreter/OptionValue.cpp +++ b/source/Interpreter/OptionValue.cpp @@ -71,6 +71,21 @@ OptionValue::GetAsBoolean () const return nullptr; } +const OptionValueChar * +OptionValue::GetAsChar () const +{ + if (GetType () == OptionValue::eTypeChar) + return static_cast(this); + return nullptr; +} + +OptionValueChar * +OptionValue::GetAsChar () +{ + if (GetType () == OptionValue::eTypeChar) + return static_cast(this); + return nullptr; +} OptionValueFileSpec * OptionValue::GetAsFileSpec () @@ -342,6 +357,27 @@ OptionValue::SetBooleanValue (bool new_value) return false; } +char +OptionValue::GetCharValue(char fail_value) const +{ + const OptionValueChar *option_value = GetAsChar(); + if (option_value) + return option_value->GetCurrentValue(); + return fail_value; +} + +char +OptionValue::SetCharValue(char new_value) +{ + OptionValueChar *option_value = GetAsChar(); + if (option_value) + { + option_value->SetCurrentValue(new_value); + return true; + } + return false; +} + int64_t OptionValue::GetEnumerationValue (int64_t fail_value) const { @@ -520,6 +556,8 @@ OptionValue::GetBuiltinTypeAsCString (Type t) case eTypeArgs: return "arguments"; case eTypeArray: return "array"; case eTypeBoolean: return "boolean"; + case eTypeChar: + return "char"; case eTypeDictionary: return "dictionary"; case eTypeEnum: return "enum"; case eTypeFileSpec: return "file"; @@ -547,6 +585,7 @@ OptionValue::CreateValueFromCStringForTypeMask (const char *value_cstr, uint32_t { case 1u << eTypeArch: value_sp.reset(new OptionValueArch()); break; case 1u << eTypeBoolean: value_sp.reset(new OptionValueBoolean(false)); break; + case 1u << eTypeChar: value_sp.reset(new OptionValueChar('\0')); break; case 1u << eTypeFileSpec: value_sp.reset(new OptionValueFileSpec()); break; case 1u << eTypeFormat: value_sp.reset(new OptionValueFormat(eFormatInvalid)); break; case 1u << eTypeSInt64: value_sp.reset(new OptionValueSInt64()); break; diff --git a/source/Interpreter/OptionValueArch.cpp b/source/Interpreter/OptionValueArch.cpp index 6d283d6b9275..7df149234bda 100644 --- a/source/Interpreter/OptionValueArch.cpp +++ b/source/Interpreter/OptionValueArch.cpp @@ -50,6 +50,7 @@ OptionValueArch::SetValueFromCString (const char *value_cstr, VarSetOperationTyp { case eVarSetOperationClear: Clear(); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -57,7 +58,10 @@ OptionValueArch::SetValueFromCString (const char *value_cstr, VarSetOperationTyp if (value_cstr && value_cstr[0]) { if (m_current_value.SetTriple (value_cstr)) + { m_value_was_set = true; + NotifyValueChanged(); + } else error.SetErrorStringWithFormat("unsupported architecture '%s'", value_cstr); } diff --git a/source/Interpreter/OptionValueArray.cpp b/source/Interpreter/OptionValueArray.cpp index 769aadd7b308..c0d48c1e7bd2 100644 --- a/source/Interpreter/OptionValueArray.cpp +++ b/source/Interpreter/OptionValueArray.cpp @@ -53,6 +53,7 @@ OptionValueArray::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint break; case eTypeBoolean: + case eTypeChar: case eTypeEnum: case eTypeFileSpec: case eTypeFormat: @@ -75,6 +76,7 @@ Error OptionValueArray::SetValueFromCString (const char *value, VarSetOperationType op) { Args args(value); + NotifyValueChanged(); return SetArgs (args, op); } diff --git a/source/Interpreter/OptionValueBoolean.cpp b/source/Interpreter/OptionValueBoolean.cpp index bf153a1442c7..71cc2afb98e1 100644 --- a/source/Interpreter/OptionValueBoolean.cpp +++ b/source/Interpreter/OptionValueBoolean.cpp @@ -45,6 +45,7 @@ OptionValueBoolean::SetValueFromCString (const char *value_cstr, { case eVarSetOperationClear: Clear(); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -56,6 +57,7 @@ OptionValueBoolean::SetValueFromCString (const char *value_cstr, { m_value_was_set = true; m_current_value = value; + NotifyValueChanged(); } else { diff --git a/source/Interpreter/OptionValueChar.cpp b/source/Interpreter/OptionValueChar.cpp new file mode 100644 index 000000000000..7a0135314c81 --- /dev/null +++ b/source/Interpreter/OptionValueChar.cpp @@ -0,0 +1,80 @@ +//===-- OptionValueChar.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Interpreter/OptionValueChar.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Stream.h" +#include "lldb/Core/StringList.h" +#include "lldb/Interpreter/Args.h" +#include "llvm/ADT/STLExtras.h" + +using namespace lldb; +using namespace lldb_private; + +void +OptionValueChar::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) +{ + if (dump_mask & eDumpOptionType) + strm.Printf ("(%s)", GetTypeAsCString ()); + + if (dump_mask & eDumpOptionValue) + { + if (dump_mask & eDumpOptionType) + strm.PutCString (" = "); + if (m_current_value != '\0') + strm.PutChar(m_current_value); + else + strm.PutCString("(null)"); + } +} + +Error +OptionValueChar::SetValueFromCString (const char *value_cstr, + VarSetOperationType op) +{ + Error error; + switch (op) + { + case eVarSetOperationClear: + Clear(); + break; + + case eVarSetOperationReplace: + case eVarSetOperationAssign: + { + bool success = false; + char char_value = Args::StringToChar(value_cstr, '\0', &success); + if (success) + { + m_current_value = char_value; + m_value_was_set = true; + } + else + error.SetErrorStringWithFormat("'%s' cannot be longer than 1 character", value_cstr); + } + break; + + default: + error = OptionValue::SetValueFromCString (value_cstr, op); + break; + } + return error; +} + +lldb::OptionValueSP +OptionValueChar::DeepCopy () const +{ + return OptionValueSP(new OptionValueChar(*this)); +} + + diff --git a/source/Interpreter/OptionValueDictionary.cpp b/source/Interpreter/OptionValueDictionary.cpp index b560937141b3..e5299f8cc390 100644 --- a/source/Interpreter/OptionValueDictionary.cpp +++ b/source/Interpreter/OptionValueDictionary.cpp @@ -64,6 +64,7 @@ OptionValueDictionary::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, break; case eTypeBoolean: + case eTypeChar: case eTypeEnum: case eTypeFileSpec: case eTypeFormat: @@ -220,7 +221,10 @@ Error OptionValueDictionary::SetValueFromCString (const char *value_cstr, VarSetOperationType op) { Args args(value_cstr); - return SetArgs (args, op); + Error error = SetArgs (args, op); + if (error.Success()) + NotifyValueChanged(); + return error; } lldb::OptionValueSP diff --git a/source/Interpreter/OptionValueEnumeration.cpp b/source/Interpreter/OptionValueEnumeration.cpp index 7aceac91b601..dbaeb185fa3a 100644 --- a/source/Interpreter/OptionValueEnumeration.cpp +++ b/source/Interpreter/OptionValueEnumeration.cpp @@ -62,6 +62,7 @@ OptionValueEnumeration::SetValueFromCString (const char *value, VarSetOperationT { case eVarSetOperationClear: Clear (); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -73,6 +74,7 @@ OptionValueEnumeration::SetValueFromCString (const char *value, VarSetOperationT if (enumerator_entry) { m_current_value = enumerator_entry->value.value; + NotifyValueChanged(); } else { diff --git a/source/Interpreter/OptionValueFileSpec.cpp b/source/Interpreter/OptionValueFileSpec.cpp index c8aaadef23bc..3f466985a83a 100644 --- a/source/Interpreter/OptionValueFileSpec.cpp +++ b/source/Interpreter/OptionValueFileSpec.cpp @@ -78,6 +78,7 @@ OptionValueFileSpec::SetValueFromCString (const char *value_cstr, { case eVarSetOperationClear: Clear (); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -100,6 +101,7 @@ OptionValueFileSpec::SetValueFromCString (const char *value_cstr, m_value_was_set = true; m_current_value.SetFile(filepath.c_str(), true); m_data_sp.reset(); + NotifyValueChanged(); } else { diff --git a/source/Interpreter/OptionValueFileSpecLIst.cpp b/source/Interpreter/OptionValueFileSpecLIst.cpp index e493c70d5a55..7150ad474643 100644 --- a/source/Interpreter/OptionValueFileSpecLIst.cpp +++ b/source/Interpreter/OptionValueFileSpecLIst.cpp @@ -51,6 +51,7 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation { case eVarSetOperationClear: Clear (); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -72,6 +73,7 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation else m_current_value.Append(file); } + NotifyValueChanged(); } } else @@ -94,6 +96,7 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation FileSpec file (args.GetArgumentAtIndex(i), false); m_current_value.Append(file); } + NotifyValueChanged(); } else { @@ -120,6 +123,7 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation FileSpec file (args.GetArgumentAtIndex(i), false); m_current_value.Insert (idx, file); } + NotifyValueChanged(); } } else @@ -155,6 +159,7 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation m_current_value.Remove (j); } } + NotifyValueChanged(); } else { @@ -172,9 +177,6 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation break; } return error; - - m_value_was_set = true; - return Error(); } lldb::OptionValueSP diff --git a/source/Interpreter/OptionValueFormat.cpp b/source/Interpreter/OptionValueFormat.cpp index 296dd983208c..d91f10b0edeb 100644 --- a/source/Interpreter/OptionValueFormat.cpp +++ b/source/Interpreter/OptionValueFormat.cpp @@ -43,6 +43,7 @@ OptionValueFormat::SetValueFromCString (const char *value_cstr, VarSetOperationT { case eVarSetOperationClear: Clear(); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -54,6 +55,7 @@ OptionValueFormat::SetValueFromCString (const char *value_cstr, VarSetOperationT { m_value_was_set = true; m_current_value = new_format; + NotifyValueChanged(); } } break; diff --git a/source/Interpreter/OptionValuePathMappings.cpp b/source/Interpreter/OptionValuePathMappings.cpp index 88a0eb7d6a3b..56f2ecf4f5fe 100644 --- a/source/Interpreter/OptionValuePathMappings.cpp +++ b/source/Interpreter/OptionValuePathMappings.cpp @@ -43,6 +43,7 @@ OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperation { case eVarSetOperationClear: Clear (); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -64,6 +65,7 @@ OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperation if (!m_path_mappings.Replace (a, b, idx, m_notify_changes)) m_path_mappings.Append(a, b, m_notify_changes); } + NotifyValueChanged(); } } else @@ -97,6 +99,7 @@ OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperation m_path_mappings.Append(a, b, m_notify_changes); m_value_was_set = true; } + NotifyValueChanged(); } break; @@ -121,6 +124,7 @@ OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperation ConstString b(args.GetArgumentAtIndex(i+1)); m_path_mappings.Insert (a, b, idx, m_notify_changes); } + NotifyValueChanged(); } } else @@ -156,6 +160,7 @@ OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperation m_path_mappings.Remove (j, m_notify_changes); } } + NotifyValueChanged(); } else { @@ -173,9 +178,6 @@ OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperation break; } return error; - - m_value_was_set = true; - return Error(); } lldb::OptionValueSP diff --git a/source/Interpreter/OptionValueProperties.cpp b/source/Interpreter/OptionValueProperties.cpp index 0497ee1c15d7..6ec2aa569fa3 100644 --- a/source/Interpreter/OptionValueProperties.cpp +++ b/source/Interpreter/OptionValueProperties.cpp @@ -80,6 +80,16 @@ OptionValueProperties::Initialize (const PropertyDefinition *defs) m_name_to_index.Sort(); } +void +OptionValueProperties::SetValueChangedCallback (uint32_t property_idx, + OptionValueChangedCallback callback, + void *baton) +{ + Property *property = ProtectedGetPropertyAtIndex (property_idx); + if (property) + property->SetValueChangedCallback (callback, baton); +} + void OptionValueProperties::AppendProperty(const ConstString &name, const ConstString &desc, diff --git a/source/Interpreter/OptionValueRegex.cpp b/source/Interpreter/OptionValueRegex.cpp index f1ba0ed04d6c..f51cf02edf56 100644 --- a/source/Interpreter/OptionValueRegex.cpp +++ b/source/Interpreter/OptionValueRegex.cpp @@ -57,6 +57,7 @@ OptionValueRegex::SetValueFromCString (const char *value_cstr, case eVarSetOperationClear: Clear(); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -64,6 +65,7 @@ OptionValueRegex::SetValueFromCString (const char *value_cstr, if (m_regex.Compile (value_cstr, m_regex.GetCompileFlags())) { m_value_was_set = true; + NotifyValueChanged(); } else { diff --git a/source/Interpreter/OptionValueSInt64.cpp b/source/Interpreter/OptionValueSInt64.cpp index 04bf9306ade6..1827cc1d873f 100644 --- a/source/Interpreter/OptionValueSInt64.cpp +++ b/source/Interpreter/OptionValueSInt64.cpp @@ -44,6 +44,7 @@ OptionValueSInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT { case eVarSetOperationClear: Clear(); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -57,6 +58,7 @@ OptionValueSInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT { m_value_was_set = true; m_current_value = value; + NotifyValueChanged(); } else error.SetErrorStringWithFormat ("%" PRIi64 " is out of range, valid values must be between %" PRIi64 " and %" PRIi64 ".", diff --git a/source/Interpreter/OptionValueString.cpp b/source/Interpreter/OptionValueString.cpp index df047bd98996..a1b80d8fc4f6 100644 --- a/source/Interpreter/OptionValueString.cpp +++ b/source/Interpreter/OptionValueString.cpp @@ -94,30 +94,32 @@ OptionValueString::SetValueFromCString (const char *value_cstr, case eVarSetOperationAppend: { - std::string new_value(m_current_value); - if (value_cstr && value_cstr[0]) - { - if (m_options.Test (eOptionEncodeCharacterEscapeSequences)) + std::string new_value(m_current_value); + if (value_cstr && value_cstr[0]) { - std::string str; - Args::EncodeEscapeSequences (value_cstr, str); - new_value.append(str); + if (m_options.Test (eOptionEncodeCharacterEscapeSequences)) + { + std::string str; + Args::EncodeEscapeSequences (value_cstr, str); + new_value.append(str); + } + else + new_value.append(value_cstr); } - else - new_value.append(value_cstr); - } - if (m_validator) - { - error = m_validator(new_value.c_str(),m_validator_baton); - if (error.Fail()) - return error; - } - m_current_value.assign(new_value); + if (m_validator) + { + error = m_validator(new_value.c_str(),m_validator_baton); + if (error.Fail()) + return error; + } + m_current_value.assign(new_value); + NotifyValueChanged(); } break; case eVarSetOperationClear: Clear (); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -137,6 +139,7 @@ OptionValueString::SetValueFromCString (const char *value_cstr, { SetCurrentValue (value_cstr); } + NotifyValueChanged(); break; } return error; diff --git a/source/Interpreter/OptionValueUInt64.cpp b/source/Interpreter/OptionValueUInt64.cpp index 56b3a1c74702..3e12c030255c 100644 --- a/source/Interpreter/OptionValueUInt64.cpp +++ b/source/Interpreter/OptionValueUInt64.cpp @@ -51,6 +51,7 @@ OptionValueUInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT { case eVarSetOperationClear: Clear (); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -62,6 +63,7 @@ OptionValueUInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT { m_value_was_set = true; m_current_value = value; + NotifyValueChanged(); } else { diff --git a/source/Interpreter/OptionValueUUID.cpp b/source/Interpreter/OptionValueUUID.cpp index 0141911d97ad..c228cf6e415e 100644 --- a/source/Interpreter/OptionValueUUID.cpp +++ b/source/Interpreter/OptionValueUUID.cpp @@ -45,6 +45,7 @@ OptionValueUUID::SetValueFromCString (const char *value_cstr, { case eVarSetOperationClear: Clear(); + NotifyValueChanged(); break; case eVarSetOperationReplace: @@ -53,7 +54,10 @@ OptionValueUUID::SetValueFromCString (const char *value_cstr, if (m_uuid.SetFromCString(value_cstr) == 0) error.SetErrorStringWithFormat ("invalid uuid string value '%s'", value_cstr); else + { m_value_was_set = true; + NotifyValueChanged(); + } } break; diff --git a/source/Interpreter/Property.cpp b/source/Interpreter/Property.cpp index 49376266b077..7f7219fc0d50 100644 --- a/source/Interpreter/Property.cpp +++ b/source/Interpreter/Property.cpp @@ -60,7 +60,11 @@ Property::Property (const PropertyDefinition &definition) : else m_value_sp.reset (new OptionValueBoolean(definition.default_uint_value != 0)); break; - + + case OptionValue::eTypeChar: + m_value_sp.reset(new OptionValueChar(Args::StringToChar(definition.default_cstr_value, '\0', nullptr))); + break; + case OptionValue::eTypeDictionary: // "definition.default_uint_value" is always a OptionValue::Type m_value_sp.reset (new OptionValueDictionary(OptionValue::ConvertTypeToMask((OptionValue::Type)definition.default_uint_value))); @@ -273,3 +277,12 @@ Property::DumpDescription (CommandInterpreter &interpreter, } } + +void +Property::SetValueChangedCallback (OptionValueChangedCallback callback, void *baton) +{ + if (m_value_sp) + m_value_sp->SetValueChangedCallback (callback, baton); +} + + diff --git a/source/Interpreter/ScriptInterpreter.cpp b/source/Interpreter/ScriptInterpreter.cpp index b6c46f83bd92..45e3b44cc0ac 100644 --- a/source/Interpreter/ScriptInterpreter.cpp +++ b/source/Interpreter/ScriptInterpreter.cpp @@ -124,6 +124,7 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, SWIGPythonUpdateSynthProviderInstance swig_update_provider, SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, + SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, SWIGPythonCallCommand swig_call_command, SWIGPythonCallModuleInit swig_call_module_init, SWIGPythonCreateOSPlugin swig_create_os_plugin, @@ -131,7 +132,10 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, - SWIGPython_GetDynamicSetting swig_plugin_get) + SWIGPythonScriptKeyword_Value swig_run_script_keyword_value, + SWIGPython_GetDynamicSetting swig_plugin_get, + SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script, + SWIGPythonCallThreadPlan swig_call_thread_plan) { #ifndef LLDB_DISABLE_PYTHON ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback, @@ -146,6 +150,7 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call swig_get_valobj_sp_from_sbvalue, swig_update_provider, swig_mighthavechildren_provider, + swig_getvalue_provider, swig_call_command, swig_call_module_init, swig_create_os_plugin, @@ -153,6 +158,9 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call swig_run_script_keyword_thread, swig_run_script_keyword_target, swig_run_script_keyword_frame, - swig_plugin_get); + swig_run_script_keyword_value, + swig_plugin_get, + swig_thread_plan_script, + swig_call_thread_plan); #endif // #ifndef LLDB_DISABLE_PYTHON } diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp index 1b24fea7c218..ab151073f9e9 100644 --- a/source/Interpreter/ScriptInterpreterPython.cpp +++ b/source/Interpreter/ScriptInterpreterPython.cpp @@ -28,15 +28,20 @@ #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Breakpoint/WatchpointOptions.h" #include "lldb/Core/Communication.h" -#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Timer.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/Pipe.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/PythonDataObjects.h" #include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" + +#if defined(_WIN32) +#include "lldb/Host/windows/ConnectionGenericFileWindows.h" +#endif using namespace lldb; using namespace lldb_private; @@ -54,6 +59,7 @@ static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue static ScriptInterpreter::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = nullptr; static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = nullptr; static ScriptInterpreter::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = nullptr; +static ScriptInterpreter::SWIGPythonGetValueSynthProviderInstance g_swig_getvalue_provider = nullptr; static ScriptInterpreter::SWIGPythonCallCommand g_swig_call_command = nullptr; static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = nullptr; static ScriptInterpreter::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = nullptr; @@ -61,7 +67,10 @@ static ScriptInterpreter::SWIGPythonScriptKeyword_Process g_swig_run_script_keyw static ScriptInterpreter::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = nullptr; static ScriptInterpreter::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = nullptr; static ScriptInterpreter::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = nullptr; +static ScriptInterpreter::SWIGPythonScriptKeyword_Value g_swig_run_script_keyword_value = nullptr; static ScriptInterpreter::SWIGPython_GetDynamicSetting g_swig_plugin_get = nullptr; +static ScriptInterpreter::SWIGPythonCreateScriptedThreadPlan g_swig_thread_plan_script = nullptr; +static ScriptInterpreter::SWIGPythonCallThreadPlan g_swig_call_thread_plan = nullptr; static std::string ReadPythonBacktrace (PyObject* py_backtrace); @@ -435,19 +444,23 @@ ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags, if (in == nullptr || out == nullptr || err == nullptr) m_interpreter.GetDebugger().AdoptTopIOHandlerFilesIfInvalid (in_sp, out_sp, err_sp); - if (in == nullptr && in_sp && (on_entry_flags & Locker::NoSTDIN) == 0) - in = in_sp->GetFile().GetStream(); - if (in) - { - m_saved_stdin.Reset(sys_module_dict.GetItemForKey("stdin")); + m_saved_stdin.Reset(); - PyObject *new_file = PyFile_FromFile (in, (char *) "", (char *) "r", nullptr); - sys_module_dict.SetItemForKey ("stdin", new_file); - Py_DECREF (new_file); + if ((on_entry_flags & Locker::NoSTDIN) == 0) + { + // STDIN is enabled + if (in == nullptr && in_sp) + in = in_sp->GetFile().GetStream(); + if (in) + { + m_saved_stdin.Reset(sys_module_dict.GetItemForKey("stdin")); + // This call can deadlock your process if the file is locked + PyObject *new_file = PyFile_FromFile (in, (char *) "", (char *) "r", nullptr); + sys_module_dict.SetItemForKey ("stdin", new_file); + Py_DECREF (new_file); + } } - else - m_saved_stdin.Reset(); - + if (out == nullptr && out_sp) out = out_sp->GetFile().GetStream(); if (out) @@ -594,9 +607,16 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec // Set output to a temporary file so we can forward the results on to the result object Pipe pipe; - if (pipe.Open()) + Error pipe_result = pipe.CreateNew(false); + if (pipe_result.Success()) { +#if defined(_WIN32) + lldb::file_t read_file = pipe.GetReadNativeHandle(); + pipe.ReleaseReadFileDescriptor(); + std::unique_ptr conn_ap(new ConnectionGenericFile(read_file, true)); +#else std::unique_ptr conn_ap(new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), true)); +#endif if (conn_ap->IsConnected()) { output_comm.SetConnection(conn_ap.release()); @@ -632,7 +652,8 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | - (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0), + (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | + ((result && result->GetInteractive()) ? 0: Locker::NoSTDIN), ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession, in_file, @@ -708,7 +729,7 @@ public: IOHandlerPythonInterpreter (Debugger &debugger, ScriptInterpreterPython *python) : - IOHandler (debugger), + IOHandler (debugger, IOHandler::Type::PythonInterpreter), m_python(python) { @@ -1616,6 +1637,87 @@ ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP return MakeScriptObject(py_return); } +lldb::ScriptInterpreterObjectSP +ScriptInterpreterPython::CreateScriptedThreadPlan (const char *class_name, + lldb::ThreadPlanSP thread_plan_sp) +{ + if (class_name == nullptr || class_name[0] == '\0') + return lldb::ScriptInterpreterObjectSP(); + + if (!thread_plan_sp.get()) + return lldb::ScriptInterpreterObjectSP(); + + Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger(); + ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); + ScriptInterpreterPython *python_interpreter = static_cast(script_interpreter); + + if (!script_interpreter) + return lldb::ScriptInterpreterObjectSP(); + + void* ret_val; + + { + Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + + ret_val = g_swig_thread_plan_script (class_name, + python_interpreter->m_dictionary_name.c_str(), + thread_plan_sp); + } + + return MakeScriptObject(ret_val); +} + +bool +ScriptInterpreterPython::ScriptedThreadPlanExplainsStop (lldb::ScriptInterpreterObjectSP implementor_sp, + Event *event, + bool &script_error) +{ + bool explains_stop = true; + if (implementor_sp) + { + Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + explains_stop = g_swig_call_thread_plan (implementor_sp->GetObject(), "explains_stop", event, script_error); + if (script_error) + return true; + } + return explains_stop; +} + +bool +ScriptInterpreterPython::ScriptedThreadPlanShouldStop (lldb::ScriptInterpreterObjectSP implementor_sp, + Event *event, + bool &script_error) +{ + bool should_stop = true; + if (implementor_sp) + { + Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + should_stop = g_swig_call_thread_plan (implementor_sp->GetObject(), "should_stop", event, script_error); + if (script_error) + return true; + } + return should_stop; +} + +lldb::StateType +ScriptInterpreterPython::ScriptedThreadPlanGetRunState (lldb::ScriptInterpreterObjectSP implementor_sp, + bool &script_error) +{ + bool should_step = false; + if (implementor_sp) + { + Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + should_step = g_swig_call_thread_plan (implementor_sp->GetObject(), "should_step", NULL, script_error); + if (script_error) + should_step = true; + } + if (should_step) + return lldb::eStateStepping; + else + return lldb::eStateRunning; +} + + lldb::ScriptInterpreterObjectSP ScriptInterpreterPython::LoadPluginModule (const FileSpec& file_spec, lldb_private::Error& error) @@ -1759,6 +1861,7 @@ bool ScriptInterpreterPython::GetScriptedSummary (const char *python_function_name, lldb::ValueObjectSP valobj, lldb::ScriptInterpreterObjectSP& callee_wrapper_sp, + const TypeSummaryOptions& options, std::string& retval) { @@ -1780,11 +1883,14 @@ ScriptInterpreterPython::GetScriptedSummary (const char *python_function_name, { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); { + TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options)); + Timer scoped_timer ("g_swig_typescript_callback","g_swig_typescript_callback"); ret_val = g_swig_typescript_callback (python_function_name, GetSessionDictionary().get(), valobj, &new_callee, + options_sp, retval); } } @@ -2056,6 +2162,42 @@ ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance (const lldb::Scr return ret_val; } +lldb::ValueObjectSP +ScriptInterpreterPython::GetSyntheticValue (const lldb::ScriptInterpreterObjectSP& implementor_sp) +{ + lldb::ValueObjectSP ret_val(nullptr); + + if (!implementor_sp) + return ret_val; + + void* implementor = implementor_sp->GetObject(); + + if (!implementor) + return ret_val; + + if (!g_swig_getvalue_provider || !g_swig_cast_to_sbvalue || !g_swig_get_valobj_sp_from_sbvalue) + return ret_val; + + { + Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + void* child_ptr = g_swig_getvalue_provider (implementor); + if (child_ptr != nullptr && child_ptr != Py_None) + { + lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr); + if (sb_value_ptr == nullptr) + Py_XDECREF(child_ptr); + else + ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr); + } + else + { + Py_XDECREF(child_ptr); + } + } + + return ret_val; +} + static std::string ReadPythonBacktrace (PyObject* py_backtrace) { @@ -2240,6 +2382,38 @@ ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, } return ret_val; } + +bool +ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, + ValueObject *value, + std::string& output, + Error& error) +{ + bool ret_val; + if (!value) + { + error.SetErrorString("no value"); + return false; + } + if (!impl_function || !impl_function[0]) + { + error.SetErrorString("no function to execute"); + return false; + } + if (!g_swig_run_script_keyword_value) + { + error.SetErrorString("internal helper function missing"); + return false; + } + { + ValueObjectSP value_sp(value->GetSP()); + Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + ret_val = g_swig_run_script_keyword_value (impl_function, m_dictionary_name.c_str(), value_sp, output); + if (!ret_val) + error.SetErrorString("python script evaluation failed"); + } + return ret_val; +} uint64_t replace_all(std::string& str, const std::string& oldStr, const std::string& newStr) { @@ -2426,7 +2600,8 @@ ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, const char* args, ScriptedCommandSynchronicity synchronicity, lldb_private::CommandReturnObject& cmd_retobj, - Error& error) + Error& error, + const lldb_private::ExecutionContext& exe_ctx) { if (!impl_function) { @@ -2441,6 +2616,7 @@ ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, } lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this(); + lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx)); if (!debugger_sp.get()) { @@ -2464,7 +2640,8 @@ ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, m_dictionary_name.c_str(), debugger_sp, args, - cmd_retobj); + cmd_retobj, + exe_ctx_ref_sp); } if (!ret_val) @@ -2529,6 +2706,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, SWIGPythonUpdateSynthProviderInstance swig_update_provider, SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, + SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, SWIGPythonCallCommand swig_call_command, SWIGPythonCallModuleInit swig_call_module_init, SWIGPythonCreateOSPlugin swig_create_os_plugin, @@ -2536,7 +2714,10 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, - SWIGPython_GetDynamicSetting swig_plugin_get) + SWIGPythonScriptKeyword_Value swig_run_script_keyword_value, + SWIGPython_GetDynamicSetting swig_plugin_get, + SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script, + SWIGPythonCallThreadPlan swig_call_thread_plan) { g_swig_init_callback = swig_init_callback; g_swig_breakpoint_callback = swig_breakpoint_callback; @@ -2550,6 +2731,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb g_swig_get_valobj_sp_from_sbvalue = swig_get_valobj_sp_from_sbvalue; g_swig_update_provider = swig_update_provider; g_swig_mighthavechildren_provider = swig_mighthavechildren_provider; + g_swig_getvalue_provider = swig_getvalue_provider; g_swig_call_command = swig_call_command; g_swig_call_module_init = swig_call_module_init; g_swig_create_os_plugin = swig_create_os_plugin; @@ -2557,7 +2739,10 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb g_swig_run_script_keyword_thread = swig_run_script_keyword_thread; g_swig_run_script_keyword_target = swig_run_script_keyword_target; g_swig_run_script_keyword_frame = swig_run_script_keyword_frame; + g_swig_run_script_keyword_value = swig_run_script_keyword_value; g_swig_plugin_get = swig_plugin_get; + g_swig_thread_plan_script = swig_thread_plan_script; + g_swig_call_thread_plan = swig_call_thread_plan; } void diff --git a/source/Interpreter/embedded_interpreter.py b/source/Interpreter/embedded_interpreter.py index 51a971690d67..10186f5a9d50 100644 --- a/source/Interpreter/embedded_interpreter.py +++ b/source/Interpreter/embedded_interpreter.py @@ -61,7 +61,7 @@ def get_terminal_size(fd): def readfunc_stdio(prompt): sys.stdout.write(prompt) - return sys.stdin.readline() + return sys.stdin.readline().rstrip() def run_python_interpreter (local_dict): # Pass in the dictionary, for continuity from one session to the next. diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp index a9f8f3b668dc..5073b13f09ab 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp @@ -801,6 +801,36 @@ ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info) break; } } + else if (name[0] == 'q') + { + switch (name[1]) + { + case '1': + switch (name[2]) + { + case '\0': + return true; // q1 is volatile + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + return true; // q10-q15 are volatile + default: + break; + }; + case '0': + case '2': + case '3': + return name[2] == '\0'; // q0-q3 are volatile + case '8': + case '9': + return name[2] == '\0'; // q8-q9 are volatile + default: + break; + } + } else if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') return true; } diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h index 6f7b339e28a2..eee43943d73a 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h @@ -53,13 +53,7 @@ public: virtual bool RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); - - virtual bool - StackUsesFrames () - { - return true; - } - + virtual bool CallFrameAddressIsValid (lldb::addr_t cfa) { @@ -88,12 +82,6 @@ public: return pc & ~(lldb::addr_t)1; } - virtual bool - FunctionCallsChangeCFA () - { - return false; - } - virtual const lldb_private::RegisterInfo * GetRegisterInfoArray (uint32_t &count); diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp index 8f7962d095fc..465257db31d8 100644 --- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp +++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp @@ -440,11 +440,11 @@ ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueO } const uint32_t type_flags = return_value_type.GetTypeInfo (NULL); - if (type_flags & ClangASTType::eTypeIsScalar || - type_flags & ClangASTType::eTypeIsPointer) + if (type_flags & eTypeIsScalar || + type_flags & eTypeIsPointer) { - if (type_flags & ClangASTType::eTypeIsInteger || - type_flags & ClangASTType::eTypeIsPointer ) + if (type_flags & eTypeIsInteger || + type_flags & eTypeIsPointer ) { // Extract the register context so we can read arguments from registers lldb::offset_t offset = 0; @@ -477,9 +477,9 @@ ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueO error.SetErrorString("We don't support returning longer than 128 bit integer values at present."); } } - else if (type_flags & ClangASTType::eTypeIsFloat) + else if (type_flags & eTypeIsFloat) { - if (type_flags & ClangASTType::eTypeIsComplex) + if (type_flags & eTypeIsComplex) { // Don't handle complex yet. error.SetErrorString ("returning complex float values are not supported"); @@ -519,7 +519,7 @@ ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueO } } } - else if (type_flags & ClangASTType::eTypeIsVector) + else if (type_flags & eTypeIsVector) { if (byte_size > 0) { @@ -874,14 +874,14 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_ const size_t byte_size = return_clang_type.GetByteSize(); const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL); - if (type_flags & ClangASTType::eTypeIsScalar || - type_flags & ClangASTType::eTypeIsPointer) + if (type_flags & eTypeIsScalar || + type_flags & eTypeIsPointer) { value.SetValueType(Value::eValueTypeScalar); bool success = false; - if (type_flags & ClangASTType::eTypeIsInteger || - type_flags & ClangASTType::eTypeIsPointer ) + if (type_flags & eTypeIsInteger || + type_flags & eTypeIsPointer ) { // Extract the register context so we can read arguments from registers if (byte_size <= 8) @@ -890,7 +890,7 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_ if (x0_reg_info) { uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(x0_reg_info, 0); - const bool is_signed = (type_flags & ClangASTType::eTypeIsSigned) != 0; + const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) { default: @@ -965,9 +965,9 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_ } } } - else if (type_flags & ClangASTType::eTypeIsFloat) + else if (type_flags & eTypeIsFloat) { - if (type_flags & ClangASTType::eTypeIsComplex) + if (type_flags & eTypeIsComplex) { // Don't handle complex yet. } @@ -1010,7 +1010,7 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_ ConstString("")); } - else if (type_flags & ClangASTType::eTypeIsVector) + else if (type_flags & eTypeIsVector) { if (byte_size > 0) { @@ -1046,8 +1046,8 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_ } } } - else if (type_flags & ClangASTType::eTypeIsStructUnion || - type_flags & ClangASTType::eTypeIsClass) + else if (type_flags & eTypeIsStructUnion || + type_flags & eTypeIsClass) { DataExtractor data; diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h index 0753b23ce2a2..6cce6a6f1174 100644 --- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h +++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h @@ -46,15 +46,7 @@ public: virtual bool RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); - - - virtual bool - StackUsesFrames () - { - // MacOSX uses frame pointers. - return true; - } - + // The arm64 ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland // code, we've seen that the stack pointer is often not aligned properly @@ -87,12 +79,6 @@ public: return true; } - virtual bool - FunctionCallsChangeCFA () - { - return false; - } - virtual const lldb_private::RegisterInfo * GetRegisterInfoArray (uint32_t &count); diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h index 43784a5c9111..d81b7a7e684b 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h @@ -64,13 +64,7 @@ public: virtual bool RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); - - virtual bool - StackUsesFrames () - { - return true; - } - + // The Darwin i386 ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland // code, we've seen that the stack pointer is often not aligned properly @@ -102,12 +96,6 @@ public: return pc <= UINT32_MAX; } - virtual bool - FunctionCallsChangeCFA () - { - return true; - } - virtual const lldb_private::RegisterInfo * GetRegisterInfoArray (uint32_t &count); diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h index 989c4a16710a..1550a38c4f3b 100644 --- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h +++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h @@ -75,13 +75,7 @@ public: virtual bool RegisterIsVolatile ( const lldb_private::RegisterInfo *reg_info ); - - virtual bool - StackUsesFrames ( void ) - { - return true; - } - + virtual bool CallFrameAddressIsValid ( lldb::addr_t cfa ) { @@ -101,12 +95,6 @@ public: return true; } - virtual bool - FunctionCallsChangeCFA ( void ) - { - return true; - } - virtual const lldb_private::RegisterInfo * GetRegisterInfoArray ( uint32_t &count ); diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp new file mode 100644 index 000000000000..adb3313d1a30 --- /dev/null +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp @@ -0,0 +1,1120 @@ +//===-- ABISysV_ppc.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ABISysV_ppc.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectRegister.h" +#include "lldb/Core/ValueObjectMemory.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Thread.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" + +using namespace lldb; +using namespace lldb_private; + +enum gcc_dwarf_regnums +{ + gcc_dwarf_r0 = 0, + gcc_dwarf_r1, + gcc_dwarf_r2, + gcc_dwarf_r3, + gcc_dwarf_r4, + gcc_dwarf_r5, + gcc_dwarf_r6, + gcc_dwarf_r7, + gcc_dwarf_r8, + gcc_dwarf_r9, + gcc_dwarf_r10, + gcc_dwarf_r11, + gcc_dwarf_r12, + gcc_dwarf_r13, + gcc_dwarf_r14, + gcc_dwarf_r15, + gcc_dwarf_r16, + gcc_dwarf_r17, + gcc_dwarf_r18, + gcc_dwarf_r19, + gcc_dwarf_r20, + gcc_dwarf_r21, + gcc_dwarf_r22, + gcc_dwarf_r23, + gcc_dwarf_r24, + gcc_dwarf_r25, + gcc_dwarf_r26, + gcc_dwarf_r27, + gcc_dwarf_r28, + gcc_dwarf_r29, + gcc_dwarf_r30, + gcc_dwarf_r31, + gcc_dwarf_f0, + gcc_dwarf_f1, + gcc_dwarf_f2, + gcc_dwarf_f3, + gcc_dwarf_f4, + gcc_dwarf_f5, + gcc_dwarf_f6, + gcc_dwarf_f7, + gcc_dwarf_f8, + gcc_dwarf_f9, + gcc_dwarf_f10, + gcc_dwarf_f11, + gcc_dwarf_f12, + gcc_dwarf_f13, + gcc_dwarf_f14, + gcc_dwarf_f15, + gcc_dwarf_f16, + gcc_dwarf_f17, + gcc_dwarf_f18, + gcc_dwarf_f19, + gcc_dwarf_f20, + gcc_dwarf_f21, + gcc_dwarf_f22, + gcc_dwarf_f23, + gcc_dwarf_f24, + gcc_dwarf_f25, + gcc_dwarf_f26, + gcc_dwarf_f27, + gcc_dwarf_f28, + gcc_dwarf_f29, + gcc_dwarf_f30, + gcc_dwarf_f31, + gcc_dwarf_cr, + gcc_dwarf_fpscr, + gcc_dwarf_xer = 101, + gcc_dwarf_lr = 108, + gcc_dwarf_ctr, + gcc_dwarf_pc, + gcc_dwarf_cfa, +}; + +enum gdb_regnums +{ + gdb_r0 = 0, + gdb_r1, + gdb_r2, + gdb_r3, + gdb_r4, + gdb_r5, + gdb_r6, + gdb_r7, + gdb_r8, + gdb_r9, + gdb_r10, + gdb_r11, + gdb_r12, + gdb_r13, + gdb_r14, + gdb_r15, + gdb_r16, + gdb_r17, + gdb_r18, + gdb_r19, + gdb_r20, + gdb_r21, + gdb_r22, + gdb_r23, + gdb_r24, + gdb_r25, + gdb_r26, + gdb_r27, + gdb_r28, + gdb_r29, + gdb_r30, + gdb_r31, + gdb_lr, + gdb_cr, + gdb_xer, + gdb_ctr, + gdb_pc, +}; + + +// Note that the size and offset will be updated by platform-specific classes. +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { #reg, alt, 8, 0, eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4}, NULL, NULL } +static const RegisterInfo +g_register_infos[] = +{ + // General purpose registers. GCC, DWARF, Generic, GDB + DEFINE_GPR(r0, NULL, gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0), + DEFINE_GPR(r1, "sp", gcc_dwarf_r1, gcc_dwarf_r1, LLDB_REGNUM_GENERIC_SP, gdb_r1), + DEFINE_GPR(r2, NULL, gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2), + DEFINE_GPR(r3, "arg1",gcc_dwarf_r3, gcc_dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, gdb_r3), + DEFINE_GPR(r4, "arg2",gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4), + DEFINE_GPR(r5, "arg3",gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, gdb_r5), + DEFINE_GPR(r6, "arg4",gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, gdb_r6), + DEFINE_GPR(r7, "arg5",gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, gdb_r7), + DEFINE_GPR(r8, "arg6",gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, gdb_r8), + DEFINE_GPR(r9, "arg7",gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, gdb_r9), + DEFINE_GPR(r10, "arg8",gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, gdb_r10), + DEFINE_GPR(r11, NULL, gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11), + DEFINE_GPR(r12, NULL, gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12), + DEFINE_GPR(r13, NULL, gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13), + DEFINE_GPR(r14, NULL, gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14), + DEFINE_GPR(r15, NULL, gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15), + DEFINE_GPR(r16, NULL, gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16), + DEFINE_GPR(r17, NULL, gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17), + DEFINE_GPR(r18, NULL, gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18), + DEFINE_GPR(r19, NULL, gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19), + DEFINE_GPR(r20, NULL, gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20), + DEFINE_GPR(r21, NULL, gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21), + DEFINE_GPR(r22, NULL, gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22), + DEFINE_GPR(r23, NULL, gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23), + DEFINE_GPR(r24, NULL, gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24), + DEFINE_GPR(r25, NULL, gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25), + DEFINE_GPR(r26, NULL, gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26), + DEFINE_GPR(r27, NULL, gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27), + DEFINE_GPR(r28, NULL, gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28), + DEFINE_GPR(r29, NULL, gcc_dwarf_r29, gcc_dwarf_r29, LLDB_INVALID_REGNUM, gdb_r29), + DEFINE_GPR(r30, NULL, gcc_dwarf_r30, gcc_dwarf_r30, LLDB_INVALID_REGNUM, gdb_r30), + DEFINE_GPR(r31, NULL, gcc_dwarf_r31, gcc_dwarf_r31, LLDB_INVALID_REGNUM, gdb_r31), + DEFINE_GPR(lr, "lr", gcc_dwarf_lr, gcc_dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_lr), + DEFINE_GPR(cr, "cr", gcc_dwarf_cr, gcc_dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(xer, "xer", gcc_dwarf_xer, gcc_dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ctr, "ctr", gcc_dwarf_ctr, gcc_dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(pc, "pc", gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL}, +}; + +static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); + +const lldb_private::RegisterInfo * +ABISysV_ppc::GetRegisterInfoArray (uint32_t &count) +{ + count = k_num_register_infos; + return g_register_infos; +} + + +size_t +ABISysV_ppc::GetRedZoneSize () const +{ + return 224; +} + +//------------------------------------------------------------------ +// Static Functions +//------------------------------------------------------------------ +ABISP +ABISysV_ppc::CreateInstance (const ArchSpec &arch) +{ + static ABISP g_abi_sp; + if (arch.GetTriple().getArch() == llvm::Triple::ppc) + { + if (!g_abi_sp) + g_abi_sp.reset (new ABISysV_ppc); + return g_abi_sp; + } + return ABISP(); +} + +bool +ABISysV_ppc::PrepareTrivialCall (Thread &thread, + addr_t sp, + addr_t func_addr, + addr_t return_addr, + llvm::ArrayRef args) const +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + { + StreamString s; + s.Printf("ABISysV_ppc::PrepareTrivialCall (tid = 0x%" PRIx64 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 ", return_addr = 0x%" PRIx64, + thread.GetID(), + (uint64_t)sp, + (uint64_t)func_addr, + (uint64_t)return_addr); + + for (size_t i = 0; i < args.size(); ++i) + s.Printf (", arg%zd = 0x%" PRIx64, i + 1, args[i]); + s.PutCString (")"); + log->PutCString(s.GetString().c_str()); + } + + RegisterContext *reg_ctx = thread.GetRegisterContext().get(); + if (!reg_ctx) + return false; + + const RegisterInfo *reg_info = NULL; + + if (args.size() > 8) // TODO handle more than 8 arguments + return false; + + for (size_t i = 0; i < args.size(); ++i) + { + reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); + if (log) + log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name); + if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) + return false; + } + + // First, align the SP + + if (log) + log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, (uint64_t)sp, (uint64_t)(sp & ~0xfull)); + + sp &= ~(0xfull); // 16-byte alignment + + sp -= 8; + + Error error; + const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); + ProcessSP process_sp (thread.GetProcess()); + + RegisterValue reg_value; + +#if 0 + // This code adds an extra frame so that we don't lose the function that we came from + // by pushing the PC and the FP and then writing the current FP to point to the FP value + // we just pushed. It is disabled for now until the stack backtracing code can be debugged. + + // Save current PC + const RegisterInfo *fp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); + if (reg_ctx->ReadRegister(pc_reg_info, reg_value)) + { + if (log) + log->Printf("Pushing the current PC onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); + + if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) + return false; + + sp -= 8; + + // Save current FP + if (reg_ctx->ReadRegister(fp_reg_info, reg_value)) + { + if (log) + log->Printf("Pushing the current FP onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); + + if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) + return false; + } + // Setup FP backchain + reg_value.SetUInt64 (sp); + + if (log) + log->Printf("Writing FP: 0x%" PRIx64 " (for FP backchain)", reg_value.GetAsUInt64()); + + if (!reg_ctx->WriteRegister(fp_reg_info, reg_value)) + { + return false; + } + + sp -= 8; + } +#endif + + if (log) + log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, (uint64_t)return_addr); + + // Save return address onto the stack + if (!process_sp->WritePointerToMemory(sp, return_addr, error)) + return false; + + // %r1 is set to the actual stack value. + + if (log) + log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + + if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp)) + return false; + + // %pc is set to the address of the called function. + + if (log) + log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr); + + if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr)) + return false; + + return true; +} + +static bool ReadIntegerArgument(Scalar &scalar, + unsigned int bit_width, + bool is_signed, + Thread &thread, + uint32_t *argument_register_ids, + unsigned int ¤t_argument_register, + addr_t ¤t_stack_argument) +{ + if (bit_width > 64) + return false; // Scalar can't hold large integer arguments + + if (current_argument_register < 6) + { + scalar = thread.GetRegisterContext()->ReadRegisterAsUnsigned(argument_register_ids[current_argument_register], 0); + current_argument_register++; + if (is_signed) + scalar.SignExtend (bit_width); + } + else + { + uint32_t byte_size = (bit_width + (8-1))/8; + Error error; + if (thread.GetProcess()->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error)) + { + current_stack_argument += byte_size; + return true; + } + return false; + } + return true; +} + +bool +ABISysV_ppc::GetArgumentValues (Thread &thread, + ValueList &values) const +{ + unsigned int num_values = values.GetSize(); + unsigned int value_index; + + // Extract the register context so we can read arguments from registers + + RegisterContext *reg_ctx = thread.GetRegisterContext().get(); + + if (!reg_ctx) + return false; + + // Get the pointer to the first stack argument so we have a place to start + // when reading data + + addr_t sp = reg_ctx->GetSP(0); + + if (!sp) + return false; + + addr_t current_stack_argument = sp + 48; // jump over return address + + uint32_t argument_register_ids[8]; + + argument_register_ids[0] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1)->kinds[eRegisterKindLLDB]; + argument_register_ids[1] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2)->kinds[eRegisterKindLLDB]; + argument_register_ids[2] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3)->kinds[eRegisterKindLLDB]; + argument_register_ids[3] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4)->kinds[eRegisterKindLLDB]; + argument_register_ids[4] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5)->kinds[eRegisterKindLLDB]; + argument_register_ids[5] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG6)->kinds[eRegisterKindLLDB]; + argument_register_ids[6] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG7)->kinds[eRegisterKindLLDB]; + argument_register_ids[7] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG8)->kinds[eRegisterKindLLDB]; + + unsigned int current_argument_register = 0; + + for (value_index = 0; + value_index < num_values; + ++value_index) + { + Value *value = values.GetValueAtIndex(value_index); + + if (!value) + return false; + + // We currently only support extracting values with Clang QualTypes. + // Do we care about others? + ClangASTType clang_type = value->GetClangType(); + if (!clang_type) + return false; + bool is_signed; + + if (clang_type.IsIntegerType (is_signed)) + { + ReadIntegerArgument(value->GetScalar(), + clang_type.GetBitSize(), + is_signed, + thread, + argument_register_ids, + current_argument_register, + current_stack_argument); + } + else if (clang_type.IsPointerType ()) + { + ReadIntegerArgument(value->GetScalar(), + clang_type.GetBitSize(), + false, + thread, + argument_register_ids, + current_argument_register, + current_stack_argument); + } + } + + return true; +} + +Error +ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp) +{ + Error error; + if (!new_value_sp) + { + error.SetErrorString("Empty value object for return value."); + return error; + } + + ClangASTType clang_type = new_value_sp->GetClangType(); + if (!clang_type) + { + error.SetErrorString ("Null clang type for return value."); + return error; + } + + Thread *thread = frame_sp->GetThread().get(); + + bool is_signed; + uint32_t count; + bool is_complex; + + RegisterContext *reg_ctx = thread->GetRegisterContext().get(); + + bool set_it_simple = false; + if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + { + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); + + DataExtractor data; + Error data_error; + size_t num_bytes = new_value_sp->GetData(data, data_error); + if (data_error.Fail()) + { + error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString()); + return error; + } + lldb::offset_t offset = 0; + if (num_bytes <= 8) + { + uint64_t raw_value = data.GetMaxU64(&offset, num_bytes); + + if (reg_ctx->WriteRegisterFromUnsigned (reg_info, raw_value)) + set_it_simple = true; + } + else + { + error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); + } + + } + else if (clang_type.IsFloatingPointType (count, is_complex)) + { + if (is_complex) + error.SetErrorString ("We don't support returning complex values at present"); + else + { + size_t bit_width = clang_type.GetBitSize(); + if (bit_width <= 64) + { + DataExtractor data; + Error data_error; + size_t num_bytes = new_value_sp->GetData(data, data_error); + if (data_error.Fail()) + { + error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString()); + return error; + } + + unsigned char buffer[16]; + ByteOrder byte_order = data.GetByteOrder(); + + data.CopyByteOrderedData (0, num_bytes, buffer, 16, byte_order); + set_it_simple = true; + } + else + { + // FIXME - don't know how to do 80 bit long doubles yet. + error.SetErrorString ("We don't support returning float values > 64 bits at present"); + } + } + } + + if (!set_it_simple) + { + // Okay we've got a structure or something that doesn't fit in a simple register. + // We should figure out where it really goes, but we don't support this yet. + error.SetErrorString ("We only support setting simple integer and float return types at present."); + } + + return error; +} + + +ValueObjectSP +ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, + ClangASTType &return_clang_type) const +{ + ValueObjectSP return_valobj_sp; + Value value; + + if (!return_clang_type) + return return_valobj_sp; + + //value.SetContext (Value::eContextTypeClangType, return_value_type); + value.SetClangType (return_clang_type); + + RegisterContext *reg_ctx = thread.GetRegisterContext().get(); + if (!reg_ctx) + return return_valobj_sp; + + const uint32_t type_flags = return_clang_type.GetTypeInfo (); + if (type_flags & eTypeIsScalar) + { + value.SetValueType(Value::eValueTypeScalar); + + bool success = false; + if (type_flags & eTypeIsInteger) + { + // Extract the register context so we can read arguments from registers + + const size_t byte_size = return_clang_type.GetByteSize(); + uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0); + const bool is_signed = (type_flags & eTypeIsSigned) != 0; + switch (byte_size) + { + default: + break; + + case sizeof(uint64_t): + if (is_signed) + value.GetScalar() = (int64_t)(raw_value); + else + value.GetScalar() = (uint64_t)(raw_value); + success = true; + break; + + case sizeof(uint32_t): + if (is_signed) + value.GetScalar() = (int32_t)(raw_value & UINT32_MAX); + else + value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX); + success = true; + break; + + case sizeof(uint16_t): + if (is_signed) + value.GetScalar() = (int16_t)(raw_value & UINT16_MAX); + else + value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX); + success = true; + break; + + case sizeof(uint8_t): + if (is_signed) + value.GetScalar() = (int8_t)(raw_value & UINT8_MAX); + else + value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX); + success = true; + break; + } + } + else if (type_flags & eTypeIsFloat) + { + if (type_flags & eTypeIsComplex) + { + // Don't handle complex yet. + } + else + { + const size_t byte_size = return_clang_type.GetByteSize(); + if (byte_size <= sizeof(long double)) + { + const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); + RegisterValue f1_value; + if (reg_ctx->ReadRegister (f1_info, f1_value)) + { + DataExtractor data; + if (f1_value.GetData(data)) + { + lldb::offset_t offset = 0; + if (byte_size == sizeof(float)) + { + value.GetScalar() = (float) data.GetFloat(&offset); + success = true; + } + else if (byte_size == sizeof(double)) + { + value.GetScalar() = (double) data.GetDouble(&offset); + success = true; + } + } + } + } + } + } + + if (success) + return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), + value, + ConstString("")); + + } + else if (type_flags & eTypeIsPointer) + { + unsigned r3_id = reg_ctx->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB]; + value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0); + value.SetValueType(Value::eValueTypeScalar); + return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), + value, + ConstString("")); + } + else if (type_flags & eTypeIsVector) + { + const size_t byte_size = return_clang_type.GetByteSize(); + if (byte_size > 0) + { + + const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v0", 0); + if (altivec_reg == NULL) + altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); + if (altivec_reg) + { + if (byte_size <= altivec_reg->byte_size) + { + ProcessSP process_sp (thread.GetProcess()); + if (process_sp) + { + std::unique_ptr heap_data_ap (new DataBufferHeap(byte_size, 0)); + const ByteOrder byte_order = process_sp->GetByteOrder(); + RegisterValue reg_value; + if (reg_ctx->ReadRegister(altivec_reg, reg_value)) + { + Error error; + if (reg_value.GetAsMemoryData (altivec_reg, + heap_data_ap->GetBytes(), + heap_data_ap->GetByteSize(), + byte_order, + error)) + { + DataExtractor data (DataBufferSP (heap_data_ap.release()), + byte_order, + process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); + return_valobj_sp = ValueObjectConstResult::Create (&thread, + return_clang_type, + ConstString(""), + data); + } + } + } + } + } + } + } + + return return_valobj_sp; +} + +ValueObjectSP +ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +{ + ValueObjectSP return_valobj_sp; + + if (!return_clang_type) + return return_valobj_sp; + + ExecutionContext exe_ctx (thread.shared_from_this()); + return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type); + if (return_valobj_sp) + return return_valobj_sp; + + RegisterContextSP reg_ctx_sp = thread.GetRegisterContext(); + if (!reg_ctx_sp) + return return_valobj_sp; + + const size_t bit_width = return_clang_type.GetBitSize(); + if (return_clang_type.IsAggregateType()) + { + Target *target = exe_ctx.GetTargetPtr(); + bool is_memory = true; + if (bit_width <= 128) + { + ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder(); + DataBufferSP data_sp (new DataBufferHeap(16, 0)); + DataExtractor return_ext (data_sp, + target_byte_order, + target->GetArchitecture().GetAddressByteSize()); + + const RegisterInfo *r3_info = reg_ctx_sp->GetRegisterInfoByName("r3", 0); + const RegisterInfo *rdx_info = reg_ctx_sp->GetRegisterInfoByName("rdx", 0); + + RegisterValue r3_value, rdx_value; + reg_ctx_sp->ReadRegister (r3_info, r3_value); + reg_ctx_sp->ReadRegister (rdx_info, rdx_value); + + DataExtractor r3_data, rdx_data; + + 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 + + const uint32_t num_children = return_clang_type.GetNumFields (); + + // Since we are in the small struct regime, assume we are not in memory. + is_memory = false; + + for (uint32_t idx = 0; idx < num_children; idx++) + { + std::string name; + uint64_t field_bit_offset = 0; + bool is_signed; + bool is_complex; + uint32_t count; + + ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + const size_t field_bit_width = field_clang_type.GetBitSize(); + + // If there are any unaligned fields, this is stored in memory. + if (field_bit_offset % field_bit_width != 0) + { + is_memory = true; + break; + } + + uint32_t field_byte_width = field_bit_width/8; + uint32_t field_byte_offset = field_bit_offset/8; + + + DataExtractor *copy_from_extractor = NULL; + uint32_t copy_from_offset = 0; + + if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ()) + { + if (integer_bytes < 8) + { + if (integer_bytes + field_byte_width <= 8) + { + // This is in RAX, copy from register to our result structure: + copy_from_extractor = &r3_data; + copy_from_offset = integer_bytes; + integer_bytes += field_byte_width; + } + else + { + // The next field wouldn't fit in the remaining space, so we pushed it to rdx. + copy_from_extractor = &rdx_data; + copy_from_offset = 0; + integer_bytes = 8 + field_byte_width; + + } + } + else if (integer_bytes + field_byte_width <= 16) + { + copy_from_extractor = &rdx_data; + copy_from_offset = integer_bytes - 8; + integer_bytes += field_byte_width; + } + else + { + // The last field didn't fit. I can't see how that would happen w/o the overall size being + // greater than 16 bytes. For now, return a NULL return value object. + return return_valobj_sp; + } + } + else if (field_clang_type.IsFloatingPointType (count, is_complex)) + { + // Structs with long doubles are always passed in memory. + if (field_bit_width == 128) + { + is_memory = true; + 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 it. If we are in an "eightbyte" with one or more ints, + // then we will be stuffed into the appropriate GPR with them. + bool in_gpr; + if (field_byte_offset % 8 == 0) + { + // We are at the beginning of one of the eightbytes, so check the next element (if any) + if (idx == num_children - 1) + in_gpr = false; + else + { + uint64_t next_field_bit_offset = 0; + ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1, + name, + &next_field_bit_offset, + NULL, + NULL); + if (next_field_clang_type.IsIntegerType (is_signed)) + in_gpr = true; + else + { + copy_from_offset = 0; + in_gpr = false; + } + } + + } + else if (field_byte_offset % 4 == 0) + { + // We are inside of an eightbyte, so see if the field before us is floating point: + // This could happen if somebody put padding in the structure. + if (idx == 0) + in_gpr = false; + else + { + uint64_t prev_field_bit_offset = 0; + ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1, + name, + &prev_field_bit_offset, + NULL, + NULL); + if (prev_field_clang_type.IsIntegerType (is_signed)) + in_gpr = true; + else + { + copy_from_offset = 4; + in_gpr = false; + } + } + + } + else + { + is_memory = true; + continue; + } + + // Okay, we've figured out whether we are in GPR or XMM, now figure out which one. + if (in_gpr) + { + if (integer_bytes < 8) + { + // This is in RAX, copy from register to our result structure: + copy_from_extractor = &r3_data; + copy_from_offset = integer_bytes; + integer_bytes += field_byte_width; + } + else + { + copy_from_extractor = &rdx_data; + copy_from_offset = integer_bytes - 8; + integer_bytes += field_byte_width; + } + } + else + { + fp_bytes += field_byte_width; + } + } + } + + // These two tests are just sanity checks. If I somehow get the + // type calculation wrong above it is better to just return nothing + // than to assert or crash. + if (!copy_from_extractor) + return return_valobj_sp; + if (copy_from_offset + field_byte_width > copy_from_extractor->GetByteSize()) + return return_valobj_sp; + + copy_from_extractor->CopyByteOrderedData (copy_from_offset, + field_byte_width, + data_sp->GetBytes() + field_byte_offset, + field_byte_width, + target_byte_order); + } + + if (!is_memory) + { + // The result is in our data buffer. Let's make a variable object out of it: + return_valobj_sp = ValueObjectConstResult::Create (&thread, + return_clang_type, + ConstString(""), + return_ext); + } + } + + + // FIXME: This is just taking a guess, r3 may very well no longer hold the return storage location. + // If we are going to do this right, when we make a new frame we should check to see if it uses a memory + // return, and if we are at the first instruction and if so stash away the return location. Then we would + // only return the memory return value if we know it is valid. + + if (is_memory) + { + unsigned r3_id = reg_ctx_sp->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB]; + lldb::addr_t storage_addr = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0); + return_valobj_sp = ValueObjectMemory::Create (&thread, + "", + Address (storage_addr, NULL), + return_clang_type); + } + } + + return return_valobj_sp; +} + +bool +ABISysV_ppc::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) +{ + unwind_plan.Clear(); + unwind_plan.SetRegisterKind (eRegisterKindDWARF); + + uint32_t lr_reg_num = gcc_dwarf_lr; + uint32_t sp_reg_num = gcc_dwarf_r1; + uint32_t pc_reg_num = gcc_dwarf_pc; + + UnwindPlan::RowSP row(new UnwindPlan::Row); + + // Our Call Frame Address is the stack pointer value + row->SetCFARegister (sp_reg_num); + + // The previous PC is in the LR + row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true); + unwind_plan.AppendRow (row); + + // All other registers are the same. + + unwind_plan.SetSourceName ("ppc at-func-entry default"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); + + return true; +} + +bool +ABISysV_ppc::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) +{ + unwind_plan.Clear(); + unwind_plan.SetRegisterKind (eRegisterKindDWARF); + + uint32_t sp_reg_num = gcc_dwarf_r1; + uint32_t pc_reg_num = gcc_dwarf_lr; + + UnwindPlan::RowSP row(new UnwindPlan::Row); + + const int32_t ptr_size = 4; + row->SetCFARegister (sp_reg_num); + row->SetCFAType(lldb_private::UnwindPlan::Row::CFAIsRegisterDereferenced); + + row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 1, true); + row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); + + unwind_plan.AppendRow (row); + unwind_plan.SetSourceName ("ppc default unwind plan"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); + unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr); + return true; +} + +bool +ABISysV_ppc::RegisterIsVolatile (const RegisterInfo *reg_info) +{ + return !RegisterIsCalleeSaved (reg_info); +} + + + +// See "Register Usage" in the +// "System V Application Binary Interface" +// "64-bit PowerPC ELF Application Binary Interface Supplement" +// current version is 1.9 released 2004 at http://refspecs.linuxfoundation.org/ELF/ppc/PPC-elf64abi-1.9.pdf + +bool +ABISysV_ppc::RegisterIsCalleeSaved (const RegisterInfo *reg_info) +{ + if (reg_info) + { + // Preserved registers are : + // r1,r2,r13-r31 + // f14-f31 (not yet) + // v20-v31 (not yet) + // vrsave (not yet) + + const char *name = reg_info->name; + if (name[0] == 'r') + { + if ((name[1] == '1' || name[1] == '2') && name[2] == '\0') + return true; + if (name[1] == '1' && name[2] > '2') + return true; + if ((name[1] == '2' || name[1] == '3') && name[2] != '\0') + return true; + } + + if (name[0] == 'f' && name[1] >= '0' && name[1] <= '9') + { + if (name[3] == '1' && name[4] >= '4') + return true; + if ((name[3] == '2' || name[3] == '3') && name[4] != '\0') + return true; + } + + if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp + return true; + if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp + return true; + if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc + return true; + } + return false; +} + + + +void +ABISysV_ppc::Initialize() +{ + PluginManager::RegisterPlugin (GetPluginNameStatic(), + "System V ABI for ppc targets", + CreateInstance); +} + +void +ABISysV_ppc::Terminate() +{ + PluginManager::UnregisterPlugin (CreateInstance); +} + +lldb_private::ConstString +ABISysV_ppc::GetPluginNameStatic() +{ + static ConstString g_name("sysv-ppc"); + return g_name; +} + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ +lldb_private::ConstString +ABISysV_ppc::GetPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +ABISysV_ppc::GetPluginVersion() +{ + return 1; +} + diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h new file mode 100644 index 000000000000..a7aad300e297 --- /dev/null +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h @@ -0,0 +1,143 @@ +//===-- ABISysV_ppc.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ABISysV_ppc_h_ +#define liblldb_ABISysV_ppc_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Target/ABI.h" + +class ABISysV_ppc : + public lldb_private::ABI +{ +public: + + ~ABISysV_ppc() + { + } + + virtual size_t + GetRedZoneSize () const; + + virtual bool + PrepareTrivialCall (lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const; + + virtual bool + GetArgumentValues (lldb_private::Thread &thread, + lldb_private::ValueList &values) const; + + virtual lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + +protected: + lldb::ValueObjectSP + GetReturnValueObjectSimple (lldb_private::Thread &thread, + lldb_private::ClangASTType &ast_type) const; + +public: + virtual lldb::ValueObjectSP + GetReturnValueObjectImpl (lldb_private::Thread &thread, + lldb_private::ClangASTType &type) const; + + virtual bool + CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + + virtual bool + CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + + virtual bool + RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); + + virtual bool + StackUsesFrames () + { + return true; + } + + // The SysV ppc ABI requires that stack frames be 16 byte aligned. + // When there is a trap handler on the stack, e.g. _sigtramp in userland + // code, we've seen that the stack pointer is often not aligned properly + // before the handler is invoked. This means that lldb will stop the unwind + // early -- before the function which caused the trap. + // + // To work around this, we relax that alignment to be just word-size (8-bytes). + // Whitelisting the trap handlers for user space would be easy (_sigtramp) but + // in other environments there can be a large number of different functions + // involved in async traps. + virtual bool + CallFrameAddressIsValid (lldb::addr_t cfa) + { + // Make sure the stack call frame addresses are 8 byte aligned + if (cfa & (8ull - 1ull)) + return false; // Not 8 byte aligned + if (cfa == 0) + return false; // Zero is not a valid stack address + return true; + } + + virtual bool + CodeAddressIsValid (lldb::addr_t pc) + { + // We have a 64 bit address space, so anything is valid as opcodes + // aren't fixed width... + return true; + } + + virtual bool + FunctionCallsChangeCFA () + { + return true; + } + + virtual const lldb_private::RegisterInfo * + GetRegisterInfoArray (uint32_t &count); + //------------------------------------------------------------------ + // Static Functions + //------------------------------------------------------------------ + static void + Initialize(); + + static void + Terminate(); + + static lldb::ABISP + CreateInstance (const lldb_private::ArchSpec &arch); + + static lldb_private::ConstString + GetPluginNameStatic(); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + virtual lldb_private::ConstString + GetPluginName(); + + virtual uint32_t + GetPluginVersion(); + +protected: + void + CreateRegisterMapIfNeeded (); + + bool + RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); + +private: + ABISysV_ppc() : lldb_private::ABI() { } // Call CreateInstance instead. +}; + +#endif // liblldb_ABI_h_ diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp new file mode 100644 index 000000000000..46f1e1023f0a --- /dev/null +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp @@ -0,0 +1,1124 @@ +//===-- ABISysV_ppc64.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ABISysV_ppc64.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectRegister.h" +#include "lldb/Core/ValueObjectMemory.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Thread.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" + +using namespace lldb; +using namespace lldb_private; + +enum gcc_dwarf_regnums +{ + gcc_dwarf_r0 = 0, + gcc_dwarf_r1, + gcc_dwarf_r2, + gcc_dwarf_r3, + gcc_dwarf_r4, + gcc_dwarf_r5, + gcc_dwarf_r6, + gcc_dwarf_r7, + gcc_dwarf_r8, + gcc_dwarf_r9, + gcc_dwarf_r10, + gcc_dwarf_r11, + gcc_dwarf_r12, + gcc_dwarf_r13, + gcc_dwarf_r14, + gcc_dwarf_r15, + gcc_dwarf_r16, + gcc_dwarf_r17, + gcc_dwarf_r18, + gcc_dwarf_r19, + gcc_dwarf_r20, + gcc_dwarf_r21, + gcc_dwarf_r22, + gcc_dwarf_r23, + gcc_dwarf_r24, + gcc_dwarf_r25, + gcc_dwarf_r26, + gcc_dwarf_r27, + gcc_dwarf_r28, + gcc_dwarf_r29, + gcc_dwarf_r30, + gcc_dwarf_r31, + gcc_dwarf_f0, + gcc_dwarf_f1, + gcc_dwarf_f2, + gcc_dwarf_f3, + gcc_dwarf_f4, + gcc_dwarf_f5, + gcc_dwarf_f6, + gcc_dwarf_f7, + gcc_dwarf_f8, + gcc_dwarf_f9, + gcc_dwarf_f10, + gcc_dwarf_f11, + gcc_dwarf_f12, + gcc_dwarf_f13, + gcc_dwarf_f14, + gcc_dwarf_f15, + gcc_dwarf_f16, + gcc_dwarf_f17, + gcc_dwarf_f18, + gcc_dwarf_f19, + gcc_dwarf_f20, + gcc_dwarf_f21, + gcc_dwarf_f22, + gcc_dwarf_f23, + gcc_dwarf_f24, + gcc_dwarf_f25, + gcc_dwarf_f26, + gcc_dwarf_f27, + gcc_dwarf_f28, + gcc_dwarf_f29, + gcc_dwarf_f30, + gcc_dwarf_f31, + gcc_dwarf_cr, + gcc_dwarf_fpscr, + gcc_dwarf_xer = 101, + gcc_dwarf_lr = 108, + gcc_dwarf_ctr, + gcc_dwarf_pc, + gcc_dwarf_cfa, +}; + +enum gdb_regnums +{ + gdb_r0 = 0, + gdb_r1, + gdb_r2, + gdb_r3, + gdb_r4, + gdb_r5, + gdb_r6, + gdb_r7, + gdb_r8, + gdb_r9, + gdb_r10, + gdb_r11, + gdb_r12, + gdb_r13, + gdb_r14, + gdb_r15, + gdb_r16, + gdb_r17, + gdb_r18, + gdb_r19, + gdb_r20, + gdb_r21, + gdb_r22, + gdb_r23, + gdb_r24, + gdb_r25, + gdb_r26, + gdb_r27, + gdb_r28, + gdb_r29, + gdb_r30, + gdb_r31, + gdb_lr, + gdb_cr, + gdb_xer, + gdb_ctr, + gdb_pc, +}; + + +// Note that the size and offset will be updated by platform-specific classes. +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { #reg, alt, 8, 0, eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4}, NULL, NULL } +static const RegisterInfo +g_register_infos[] = +{ + // General purpose registers. GCC, DWARF, Generic, GDB + DEFINE_GPR(r0, NULL, gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0), + DEFINE_GPR(r1, "sp", gcc_dwarf_r1, gcc_dwarf_r1, LLDB_REGNUM_GENERIC_SP, gdb_r1), + DEFINE_GPR(r2, NULL, gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2), + DEFINE_GPR(r3, "arg1",gcc_dwarf_r3, gcc_dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, gdb_r3), + DEFINE_GPR(r4, "arg2",gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4), + DEFINE_GPR(r5, "arg3",gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, gdb_r5), + DEFINE_GPR(r6, "arg4",gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, gdb_r6), + DEFINE_GPR(r7, "arg5",gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, gdb_r7), + DEFINE_GPR(r8, "arg6",gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, gdb_r8), + DEFINE_GPR(r9, "arg7",gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, gdb_r9), + DEFINE_GPR(r10, "arg8",gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, gdb_r10), + DEFINE_GPR(r11, NULL, gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11), + DEFINE_GPR(r12, NULL, gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12), + DEFINE_GPR(r13, NULL, gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13), + DEFINE_GPR(r14, NULL, gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14), + DEFINE_GPR(r15, NULL, gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15), + DEFINE_GPR(r16, NULL, gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16), + DEFINE_GPR(r17, NULL, gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17), + DEFINE_GPR(r18, NULL, gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18), + DEFINE_GPR(r19, NULL, gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19), + DEFINE_GPR(r20, NULL, gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20), + DEFINE_GPR(r21, NULL, gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21), + DEFINE_GPR(r22, NULL, gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22), + DEFINE_GPR(r23, NULL, gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23), + DEFINE_GPR(r24, NULL, gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24), + DEFINE_GPR(r25, NULL, gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25), + DEFINE_GPR(r26, NULL, gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26), + DEFINE_GPR(r27, NULL, gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27), + DEFINE_GPR(r28, NULL, gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28), + DEFINE_GPR(r29, NULL, gcc_dwarf_r29, gcc_dwarf_r29, LLDB_INVALID_REGNUM, gdb_r29), + DEFINE_GPR(r30, NULL, gcc_dwarf_r30, gcc_dwarf_r30, LLDB_INVALID_REGNUM, gdb_r30), + DEFINE_GPR(r31, NULL, gcc_dwarf_r31, gcc_dwarf_r31, LLDB_INVALID_REGNUM, gdb_r31), + DEFINE_GPR(lr, "lr", gcc_dwarf_lr, gcc_dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_lr), + DEFINE_GPR(cr, "cr", gcc_dwarf_cr, gcc_dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(xer, "xer", gcc_dwarf_xer, gcc_dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ctr, "ctr", gcc_dwarf_ctr, gcc_dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(pc, "pc", gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL}, +}; + +static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); + +const lldb_private::RegisterInfo * +ABISysV_ppc64::GetRegisterInfoArray (uint32_t &count) +{ + count = k_num_register_infos; + return g_register_infos; +} + + +size_t +ABISysV_ppc64::GetRedZoneSize () const +{ + return 224; +} + +//------------------------------------------------------------------ +// Static Functions +//------------------------------------------------------------------ +ABISP +ABISysV_ppc64::CreateInstance (const ArchSpec &arch) +{ + static ABISP g_abi_sp; + if (arch.GetTriple().getArch() == llvm::Triple::ppc64) + { + if (!g_abi_sp) + g_abi_sp.reset (new ABISysV_ppc64); + return g_abi_sp; + } + return ABISP(); +} + +bool +ABISysV_ppc64::PrepareTrivialCall (Thread &thread, + addr_t sp, + addr_t func_addr, + addr_t return_addr, + llvm::ArrayRef args) const +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + { + StreamString s; + s.Printf("ABISysV_ppc64::PrepareTrivialCall (tid = 0x%" PRIx64 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 ", return_addr = 0x%" PRIx64, + thread.GetID(), + (uint64_t)sp, + (uint64_t)func_addr, + (uint64_t)return_addr); + + for (size_t i = 0; i < args.size(); ++i) + s.Printf (", arg%zd = 0x%" PRIx64, i + 1, args[i]); + s.PutCString (")"); + log->PutCString(s.GetString().c_str()); + } + + RegisterContext *reg_ctx = thread.GetRegisterContext().get(); + if (!reg_ctx) + return false; + + const RegisterInfo *reg_info = NULL; + + if (args.size() > 8) // TODO handle more than 8 arguments + return false; + + for (size_t i = 0; i < args.size(); ++i) + { + reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); + if (log) + log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name); + if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) + return false; + } + + // First, align the SP + + if (log) + log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, (uint64_t)sp, (uint64_t)(sp & ~0xfull)); + + sp &= ~(0xfull); // 16-byte alignment + + sp -= 8; + + Error error; + const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); + ProcessSP process_sp (thread.GetProcess()); + + RegisterValue reg_value; + +#if 0 + // This code adds an extra frame so that we don't lose the function that we came from + // by pushing the PC and the FP and then writing the current FP to point to the FP value + // we just pushed. It is disabled for now until the stack backtracing code can be debugged. + + // Save current PC + const RegisterInfo *fp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); + if (reg_ctx->ReadRegister(pc_reg_info, reg_value)) + { + if (log) + log->Printf("Pushing the current PC onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); + + if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) + return false; + + sp -= 8; + + // Save current FP + if (reg_ctx->ReadRegister(fp_reg_info, reg_value)) + { + if (log) + log->Printf("Pushing the current FP onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); + + if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) + return false; + } + // Setup FP backchain + reg_value.SetUInt64 (sp); + + if (log) + log->Printf("Writing FP: 0x%" PRIx64 " (for FP backchain)", reg_value.GetAsUInt64()); + + if (!reg_ctx->WriteRegister(fp_reg_info, reg_value)) + { + return false; + } + + sp -= 8; + } +#endif + + if (log) + log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, (uint64_t)return_addr); + + // Save return address onto the stack + if (!process_sp->WritePointerToMemory(sp, return_addr, error)) + return false; + + // %r1 is set to the actual stack value. + + if (log) + log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + + if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp)) + return false; + + // %pc is set to the address of the called function. + + if (log) + log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr); + + if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr)) + return false; + + return true; +} + +static bool ReadIntegerArgument(Scalar &scalar, + unsigned int bit_width, + bool is_signed, + Thread &thread, + uint32_t *argument_register_ids, + unsigned int ¤t_argument_register, + addr_t ¤t_stack_argument) +{ + if (bit_width > 64) + return false; // Scalar can't hold large integer arguments + + if (current_argument_register < 6) + { + scalar = thread.GetRegisterContext()->ReadRegisterAsUnsigned(argument_register_ids[current_argument_register], 0); + current_argument_register++; + if (is_signed) + scalar.SignExtend (bit_width); + } + else + { + uint32_t byte_size = (bit_width + (8-1))/8; + Error error; + if (thread.GetProcess()->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error)) + { + current_stack_argument += byte_size; + return true; + } + return false; + } + return true; +} + +bool +ABISysV_ppc64::GetArgumentValues (Thread &thread, + ValueList &values) const +{ + unsigned int num_values = values.GetSize(); + unsigned int value_index; + + // Extract the register context so we can read arguments from registers + + RegisterContext *reg_ctx = thread.GetRegisterContext().get(); + + if (!reg_ctx) + return false; + + // Get the pointer to the first stack argument so we have a place to start + // when reading data + + addr_t sp = reg_ctx->GetSP(0); + + if (!sp) + return false; + + addr_t current_stack_argument = sp + 48; // jump over return address + + uint32_t argument_register_ids[8]; + + argument_register_ids[0] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1)->kinds[eRegisterKindLLDB]; + argument_register_ids[1] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2)->kinds[eRegisterKindLLDB]; + argument_register_ids[2] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3)->kinds[eRegisterKindLLDB]; + argument_register_ids[3] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4)->kinds[eRegisterKindLLDB]; + argument_register_ids[4] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5)->kinds[eRegisterKindLLDB]; + argument_register_ids[5] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG6)->kinds[eRegisterKindLLDB]; + argument_register_ids[6] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG7)->kinds[eRegisterKindLLDB]; + argument_register_ids[7] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG8)->kinds[eRegisterKindLLDB]; + + unsigned int current_argument_register = 0; + + for (value_index = 0; + value_index < num_values; + ++value_index) + { + Value *value = values.GetValueAtIndex(value_index); + + if (!value) + return false; + + // We currently only support extracting values with Clang QualTypes. + // Do we care about others? + ClangASTType clang_type = value->GetClangType(); + if (!clang_type) + return false; + bool is_signed; + + if (clang_type.IsIntegerType (is_signed)) + { + ReadIntegerArgument(value->GetScalar(), + clang_type.GetBitSize(), + is_signed, + thread, + argument_register_ids, + current_argument_register, + current_stack_argument); + } + else if (clang_type.IsPointerType ()) + { + ReadIntegerArgument(value->GetScalar(), + clang_type.GetBitSize(), + false, + thread, + argument_register_ids, + current_argument_register, + current_stack_argument); + } + } + + return true; +} + +Error +ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp) +{ + Error error; + if (!new_value_sp) + { + error.SetErrorString("Empty value object for return value."); + return error; + } + + ClangASTType clang_type = new_value_sp->GetClangType(); + if (!clang_type) + { + error.SetErrorString ("Null clang type for return value."); + return error; + } + + Thread *thread = frame_sp->GetThread().get(); + + bool is_signed; + uint32_t count; + bool is_complex; + + RegisterContext *reg_ctx = thread->GetRegisterContext().get(); + + bool set_it_simple = false; + if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + { + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); + + DataExtractor data; + Error data_error; + size_t num_bytes = new_value_sp->GetData(data, data_error); + if (data_error.Fail()) + { + error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString()); + return error; + } + lldb::offset_t offset = 0; + if (num_bytes <= 8) + { + uint64_t raw_value = data.GetMaxU64(&offset, num_bytes); + + if (reg_ctx->WriteRegisterFromUnsigned (reg_info, raw_value)) + set_it_simple = true; + } + else + { + error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); + } + + } + else if (clang_type.IsFloatingPointType (count, is_complex)) + { + if (is_complex) + error.SetErrorString ("We don't support returning complex values at present"); + else + { + size_t bit_width = clang_type.GetBitSize(); + if (bit_width <= 64) + { + DataExtractor data; + Error data_error; + size_t num_bytes = new_value_sp->GetData(data, data_error); + if (data_error.Fail()) + { + error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString()); + return error; + } + + unsigned char buffer[16]; + ByteOrder byte_order = data.GetByteOrder(); + + data.CopyByteOrderedData (0, num_bytes, buffer, 16, byte_order); + set_it_simple = true; + } + else + { + // FIXME - don't know how to do 80 bit long doubles yet. + error.SetErrorString ("We don't support returning float values > 64 bits at present"); + } + } + } + + if (!set_it_simple) + { + // Okay we've got a structure or something that doesn't fit in a simple register. + // We should figure out where it really goes, but we don't support this yet. + error.SetErrorString ("We only support setting simple integer and float return types at present."); + } + + return error; +} + + +ValueObjectSP +ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, + ClangASTType &return_clang_type) const +{ + ValueObjectSP return_valobj_sp; + Value value; + + if (!return_clang_type) + return return_valobj_sp; + + //value.SetContext (Value::eContextTypeClangType, return_value_type); + value.SetClangType (return_clang_type); + + RegisterContext *reg_ctx = thread.GetRegisterContext().get(); + if (!reg_ctx) + return return_valobj_sp; + + const uint32_t type_flags = return_clang_type.GetTypeInfo (); + if (type_flags & eTypeIsScalar) + { + value.SetValueType(Value::eValueTypeScalar); + + bool success = false; + if (type_flags & eTypeIsInteger) + { + // Extract the register context so we can read arguments from registers + + const size_t byte_size = return_clang_type.GetByteSize(); + uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0); + const bool is_signed = (type_flags & eTypeIsSigned) != 0; + switch (byte_size) + { + default: + break; + + case sizeof(uint64_t): + if (is_signed) + value.GetScalar() = (int64_t)(raw_value); + else + value.GetScalar() = (uint64_t)(raw_value); + success = true; + break; + + case sizeof(uint32_t): + if (is_signed) + value.GetScalar() = (int32_t)(raw_value & UINT32_MAX); + else + value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX); + success = true; + break; + + case sizeof(uint16_t): + if (is_signed) + value.GetScalar() = (int16_t)(raw_value & UINT16_MAX); + else + value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX); + success = true; + break; + + case sizeof(uint8_t): + if (is_signed) + value.GetScalar() = (int8_t)(raw_value & UINT8_MAX); + else + value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX); + success = true; + break; + } + } + else if (type_flags & eTypeIsFloat) + { + if (type_flags & eTypeIsComplex) + { + // Don't handle complex yet. + } + else + { + const size_t byte_size = return_clang_type.GetByteSize(); + if (byte_size <= sizeof(long double)) + { + const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); + RegisterValue f1_value; + if (reg_ctx->ReadRegister (f1_info, f1_value)) + { + DataExtractor data; + if (f1_value.GetData(data)) + { + lldb::offset_t offset = 0; + if (byte_size == sizeof(float)) + { + value.GetScalar() = (float) data.GetFloat(&offset); + success = true; + } + else if (byte_size == sizeof(double)) + { + value.GetScalar() = (double) data.GetDouble(&offset); + success = true; + } + } + } + } + } + } + + if (success) + return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), + value, + ConstString("")); + + } + else if (type_flags & eTypeIsPointer) + { + unsigned r3_id = reg_ctx->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB]; + value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0); + value.SetValueType(Value::eValueTypeScalar); + return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), + value, + ConstString("")); + } + else if (type_flags & eTypeIsVector) + { + const size_t byte_size = return_clang_type.GetByteSize(); + if (byte_size > 0) + { + + const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v0", 0); + if (altivec_reg == NULL) + altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); + if (altivec_reg) + { + if (byte_size <= altivec_reg->byte_size) + { + ProcessSP process_sp (thread.GetProcess()); + if (process_sp) + { + std::unique_ptr heap_data_ap (new DataBufferHeap(byte_size, 0)); + const ByteOrder byte_order = process_sp->GetByteOrder(); + RegisterValue reg_value; + if (reg_ctx->ReadRegister(altivec_reg, reg_value)) + { + Error error; + if (reg_value.GetAsMemoryData (altivec_reg, + heap_data_ap->GetBytes(), + heap_data_ap->GetByteSize(), + byte_order, + error)) + { + DataExtractor data (DataBufferSP (heap_data_ap.release()), + byte_order, + process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); + return_valobj_sp = ValueObjectConstResult::Create (&thread, + return_clang_type, + ConstString(""), + data); + } + } + } + } + } + } + } + + return return_valobj_sp; +} + +ValueObjectSP +ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +{ + ValueObjectSP return_valobj_sp; + + if (!return_clang_type) + return return_valobj_sp; + + ExecutionContext exe_ctx (thread.shared_from_this()); + return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type); + if (return_valobj_sp) + return return_valobj_sp; + + RegisterContextSP reg_ctx_sp = thread.GetRegisterContext(); + if (!reg_ctx_sp) + return return_valobj_sp; + + const size_t bit_width = return_clang_type.GetBitSize(); + if (return_clang_type.IsAggregateType()) + { + Target *target = exe_ctx.GetTargetPtr(); + bool is_memory = true; + if (bit_width <= 128) + { + ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder(); + DataBufferSP data_sp (new DataBufferHeap(16, 0)); + DataExtractor return_ext (data_sp, + target_byte_order, + target->GetArchitecture().GetAddressByteSize()); + + const RegisterInfo *r3_info = reg_ctx_sp->GetRegisterInfoByName("r3", 0); + const RegisterInfo *rdx_info = reg_ctx_sp->GetRegisterInfoByName("rdx", 0); + + RegisterValue r3_value, rdx_value; + reg_ctx_sp->ReadRegister (r3_info, r3_value); + reg_ctx_sp->ReadRegister (rdx_info, rdx_value); + + DataExtractor r3_data, rdx_data; + + 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 + + const uint32_t num_children = return_clang_type.GetNumFields (); + + // Since we are in the small struct regime, assume we are not in memory. + is_memory = false; + + for (uint32_t idx = 0; idx < num_children; idx++) + { + std::string name; + uint64_t field_bit_offset = 0; + bool is_signed; + bool is_complex; + uint32_t count; + + ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + const size_t field_bit_width = field_clang_type.GetBitSize(); + + // If there are any unaligned fields, this is stored in memory. + if (field_bit_offset % field_bit_width != 0) + { + is_memory = true; + break; + } + + uint32_t field_byte_width = field_bit_width/8; + uint32_t field_byte_offset = field_bit_offset/8; + + + DataExtractor *copy_from_extractor = NULL; + uint32_t copy_from_offset = 0; + + if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ()) + { + if (integer_bytes < 8) + { + if (integer_bytes + field_byte_width <= 8) + { + // This is in RAX, copy from register to our result structure: + copy_from_extractor = &r3_data; + copy_from_offset = integer_bytes; + integer_bytes += field_byte_width; + } + else + { + // The next field wouldn't fit in the remaining space, so we pushed it to rdx. + copy_from_extractor = &rdx_data; + copy_from_offset = 0; + integer_bytes = 8 + field_byte_width; + + } + } + else if (integer_bytes + field_byte_width <= 16) + { + copy_from_extractor = &rdx_data; + copy_from_offset = integer_bytes - 8; + integer_bytes += field_byte_width; + } + else + { + // The last field didn't fit. I can't see how that would happen w/o the overall size being + // greater than 16 bytes. For now, return a NULL return value object. + return return_valobj_sp; + } + } + else if (field_clang_type.IsFloatingPointType (count, is_complex)) + { + // Structs with long doubles are always passed in memory. + if (field_bit_width == 128) + { + is_memory = true; + 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 it. If we are in an "eightbyte" with one or more ints, + // then we will be stuffed into the appropriate GPR with them. + bool in_gpr; + if (field_byte_offset % 8 == 0) + { + // We are at the beginning of one of the eightbytes, so check the next element (if any) + if (idx == num_children - 1) + in_gpr = false; + else + { + uint64_t next_field_bit_offset = 0; + ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1, + name, + &next_field_bit_offset, + NULL, + NULL); + if (next_field_clang_type.IsIntegerType (is_signed)) + in_gpr = true; + else + { + copy_from_offset = 0; + in_gpr = false; + } + } + + } + else if (field_byte_offset % 4 == 0) + { + // We are inside of an eightbyte, so see if the field before us is floating point: + // This could happen if somebody put padding in the structure. + if (idx == 0) + in_gpr = false; + else + { + uint64_t prev_field_bit_offset = 0; + ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1, + name, + &prev_field_bit_offset, + NULL, + NULL); + if (prev_field_clang_type.IsIntegerType (is_signed)) + in_gpr = true; + else + { + copy_from_offset = 4; + in_gpr = false; + } + } + + } + else + { + is_memory = true; + continue; + } + + // Okay, we've figured out whether we are in GPR or XMM, now figure out which one. + if (in_gpr) + { + if (integer_bytes < 8) + { + // This is in RAX, copy from register to our result structure: + copy_from_extractor = &r3_data; + copy_from_offset = integer_bytes; + integer_bytes += field_byte_width; + } + else + { + copy_from_extractor = &rdx_data; + copy_from_offset = integer_bytes - 8; + integer_bytes += field_byte_width; + } + } + else + { + fp_bytes += field_byte_width; + } + } + } + + // These two tests are just sanity checks. If I somehow get the + // type calculation wrong above it is better to just return nothing + // than to assert or crash. + if (!copy_from_extractor) + return return_valobj_sp; + if (copy_from_offset + field_byte_width > copy_from_extractor->GetByteSize()) + return return_valobj_sp; + + copy_from_extractor->CopyByteOrderedData (copy_from_offset, + field_byte_width, + data_sp->GetBytes() + field_byte_offset, + field_byte_width, + target_byte_order); + } + + if (!is_memory) + { + // The result is in our data buffer. Let's make a variable object out of it: + return_valobj_sp = ValueObjectConstResult::Create (&thread, + return_clang_type, + ConstString(""), + return_ext); + } + } + + + // FIXME: This is just taking a guess, r3 may very well no longer hold the return storage location. + // If we are going to do this right, when we make a new frame we should check to see if it uses a memory + // return, and if we are at the first instruction and if so stash away the return location. Then we would + // only return the memory return value if we know it is valid. + + if (is_memory) + { + unsigned r3_id = reg_ctx_sp->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB]; + lldb::addr_t storage_addr = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0); + return_valobj_sp = ValueObjectMemory::Create (&thread, + "", + Address (storage_addr, NULL), + return_clang_type); + } + } + + return return_valobj_sp; +} + +bool +ABISysV_ppc64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) +{ + unwind_plan.Clear(); + unwind_plan.SetRegisterKind (eRegisterKindDWARF); + + uint32_t lr_reg_num = gcc_dwarf_lr; + uint32_t sp_reg_num = gcc_dwarf_r1; + uint32_t pc_reg_num = gcc_dwarf_pc; + + UnwindPlan::RowSP row(new UnwindPlan::Row); + + // Our Call Frame Address is the stack pointer value + row->SetCFARegister (sp_reg_num); + + // The previous PC is in the LR + row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true); + unwind_plan.AppendRow (row); + + // All other registers are the same. + + unwind_plan.SetSourceName ("ppc64 at-func-entry default"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); + + return true; +} + +bool +ABISysV_ppc64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) +{ + unwind_plan.Clear(); + unwind_plan.SetRegisterKind (eRegisterKindDWARF); + + uint32_t sp_reg_num = gcc_dwarf_r1; + uint32_t pc_reg_num = gcc_dwarf_lr; + + UnwindPlan::RowSP row(new UnwindPlan::Row); + + const int32_t ptr_size = 8; + row->SetCFARegister (sp_reg_num); + row->SetCFAType(lldb_private::UnwindPlan::Row::CFAIsRegisterDereferenced); + + row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true); + row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); + row->SetRegisterLocationToAtCFAPlusOffset(gcc_dwarf_cr, ptr_size, true); + + unwind_plan.AppendRow (row); + unwind_plan.SetSourceName ("ppc64 default unwind plan"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); + unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr); + return true; +} + +bool +ABISysV_ppc64::RegisterIsVolatile (const RegisterInfo *reg_info) +{ + return !RegisterIsCalleeSaved (reg_info); +} + + + +// See "Register Usage" in the +// "System V Application Binary Interface" +// "64-bit PowerPC ELF Application Binary Interface Supplement" +// current version is 1.9 released 2004 at http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.pdf + +bool +ABISysV_ppc64::RegisterIsCalleeSaved (const RegisterInfo *reg_info) +{ + if (reg_info) + { + // Preserved registers are : + // r1,r2,r13-r31 + // cr2-cr4 (partially preserved) + // f14-f31 (not yet) + // v20-v31 (not yet) + // vrsave (not yet) + + const char *name = reg_info->name; + if (name[0] == 'r') + { + if ((name[1] == '1' || name[1] == '2') && name[2] == '\0') + return true; + if (name[1] == '1' && name[2] > '2') + return true; + if ((name[1] == '2' || name[1] == '3') && name[2] != '\0') + return true; + } + + if (name[0] == 'f' && name[1] >= '0' && name[2] <= '9') + { + if (name[2] == '\0') + return false; + if (name[1] == '1' && name[2] >= '4') + return true; + if ((name[1] == '2' || name[1] == '3') && name[2] != '\0') + return true; + } + + if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp + return true; + if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp + return true; + if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc + return true; + } + return false; +} + + + +void +ABISysV_ppc64::Initialize() +{ + PluginManager::RegisterPlugin (GetPluginNameStatic(), + "System V ABI for ppc64 targets", + CreateInstance); +} + +void +ABISysV_ppc64::Terminate() +{ + PluginManager::UnregisterPlugin (CreateInstance); +} + +lldb_private::ConstString +ABISysV_ppc64::GetPluginNameStatic() +{ + static ConstString g_name("sysv-ppc64"); + return g_name; +} + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ +lldb_private::ConstString +ABISysV_ppc64::GetPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +ABISysV_ppc64::GetPluginVersion() +{ + return 1; +} + diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h new file mode 100644 index 000000000000..d77cb9f1efe3 --- /dev/null +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h @@ -0,0 +1,143 @@ +//===-- ABISysV_ppc64.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ABISysV_ppc64_h_ +#define liblldb_ABISysV_ppc64_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Target/ABI.h" + +class ABISysV_ppc64 : + public lldb_private::ABI +{ +public: + + ~ABISysV_ppc64() + { + } + + virtual size_t + GetRedZoneSize () const; + + virtual bool + PrepareTrivialCall (lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const; + + virtual bool + GetArgumentValues (lldb_private::Thread &thread, + lldb_private::ValueList &values) const; + + virtual lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + +protected: + lldb::ValueObjectSP + GetReturnValueObjectSimple (lldb_private::Thread &thread, + lldb_private::ClangASTType &ast_type) const; + +public: + virtual lldb::ValueObjectSP + GetReturnValueObjectImpl (lldb_private::Thread &thread, + lldb_private::ClangASTType &type) const; + + virtual bool + CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + + virtual bool + CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + + virtual bool + RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); + + virtual bool + StackUsesFrames () + { + return true; + } + + // The SysV ppc64 ABI requires that stack frames be 16 byte aligned. + // When there is a trap handler on the stack, e.g. _sigtramp in userland + // code, we've seen that the stack pointer is often not aligned properly + // before the handler is invoked. This means that lldb will stop the unwind + // early -- before the function which caused the trap. + // + // To work around this, we relax that alignment to be just word-size (8-bytes). + // Whitelisting the trap handlers for user space would be easy (_sigtramp) but + // in other environments there can be a large number of different functions + // involved in async traps. + virtual bool + CallFrameAddressIsValid (lldb::addr_t cfa) + { + // Make sure the stack call frame addresses are 8 byte aligned + if (cfa & (8ull - 1ull)) + return false; // Not 8 byte aligned + if (cfa == 0) + return false; // Zero is not a valid stack address + return true; + } + + virtual bool + CodeAddressIsValid (lldb::addr_t pc) + { + // We have a 64 bit address space, so anything is valid as opcodes + // aren't fixed width... + return true; + } + + virtual bool + FunctionCallsChangeCFA () + { + return true; + } + + virtual const lldb_private::RegisterInfo * + GetRegisterInfoArray (uint32_t &count); + //------------------------------------------------------------------ + // Static Functions + //------------------------------------------------------------------ + static void + Initialize(); + + static void + Terminate(); + + static lldb::ABISP + CreateInstance (const lldb_private::ArchSpec &arch); + + static lldb_private::ConstString + GetPluginNameStatic(); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + virtual lldb_private::ConstString + GetPluginName(); + + virtual uint32_t + GetPluginVersion(); + +protected: + void + CreateRegisterMapIfNeeded (); + + bool + RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); + +private: + ABISysV_ppc64() : lldb_private::ABI() { } // Call CreateInstance instead. +}; + +#endif // liblldb_ABI_h_ diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp index b537415bf055..776e7fea67c7 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -649,18 +649,18 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, return return_valobj_sp; const uint32_t type_flags = return_clang_type.GetTypeInfo (); - if (type_flags & ClangASTType::eTypeIsScalar) + if (type_flags & eTypeIsScalar) { value.SetValueType(Value::eValueTypeScalar); bool success = false; - if (type_flags & ClangASTType::eTypeIsInteger) + if (type_flags & eTypeIsInteger) { // Extract the register context so we can read arguments from registers const size_t byte_size = return_clang_type.GetByteSize(); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("rax", 0), 0); - const bool is_signed = (type_flags & ClangASTType::eTypeIsSigned) != 0; + const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) { default: @@ -699,9 +699,9 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, break; } } - else if (type_flags & ClangASTType::eTypeIsFloat) + else if (type_flags & eTypeIsFloat) { - if (type_flags & ClangASTType::eTypeIsComplex) + if (type_flags & eTypeIsComplex) { // Don't handle complex yet. } @@ -744,7 +744,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, ConstString("")); } - else if (type_flags & ClangASTType::eTypeIsPointer) + else if (type_flags & eTypeIsPointer) { unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB]; value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0); @@ -753,7 +753,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, value, ConstString("")); } - else if (type_flags & ClangASTType::eTypeIsVector) + else if (type_flags & eTypeIsVector) { const size_t byte_size = return_clang_type.GetByteSize(); if (byte_size > 0) diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h index 7fd1b6c4b0f3..6fefcc2a9c74 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h @@ -61,13 +61,7 @@ public: virtual bool RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); - - virtual bool - StackUsesFrames () - { - return true; - } - + // The SysV x86_64 ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland // code, we've seen that the stack pointer is often not aligned properly @@ -97,12 +91,6 @@ public: return true; } - virtual bool - FunctionCallsChangeCFA () - { - return true; - } - virtual const lldb_private::RegisterInfo * GetRegisterInfoArray (uint32_t &count); //------------------------------------------------------------------ diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp index c14371d0589c..97ddbef0e307 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -21,7 +21,6 @@ #include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MemoryObject.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/ADT/SmallString.h" @@ -489,41 +488,19 @@ DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler() { } -namespace { - // This is the memory object we use in GetInstruction. - class LLDBDisasmMemoryObject : public llvm::MemoryObject { - const uint8_t *m_bytes; - uint64_t m_size; - uint64_t m_base_PC; - public: - LLDBDisasmMemoryObject(const uint8_t *bytes, uint64_t size, uint64_t basePC) : - m_bytes(bytes), m_size(size), m_base_PC(basePC) {} - - uint64_t getBase() const { return m_base_PC; } - uint64_t getExtent() const { return m_size; } - - int readByte(uint64_t addr, uint8_t *byte) const { - if (addr - m_base_PC >= m_size) - return -1; - *byte = m_bytes[addr - m_base_PC]; - return 0; - } - }; -} // End Anonymous Namespace - uint64_t DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst) { - LLDBDisasmMemoryObject memory_object (opcode_data, opcode_data_len, pc); + llvm::ArrayRef data(opcode_data, opcode_data_len); llvm::MCDisassembler::DecodeStatus status; uint64_t new_inst_size; status = m_disasm_ap->getInstruction(mc_inst, new_inst_size, - memory_object, + data, pc, llvm::nulls(), llvm::nulls()); @@ -832,11 +809,19 @@ const char *DisassemblerLLVMC::SymbolLookup (uint64_t value, value_so_addr.Dump (&ss, target, - Address::DumpStyleResolvedDescriptionNoModule, + Address::DumpStyleResolvedDescriptionNoFunctionArguments, Address::DumpStyleSectionNameOffset); if (!ss.GetString().empty()) { + // If Address::Dump returned a multi-line description, most commonly seen when we + // have multiple levels of inlined functions at an address, only show the first line. + std::string &str(ss.GetString()); + size_t first_eol_char = str.find_first_of ("\r\n"); + if (first_eol_char != std::string::npos) + { + str.erase (first_eol_char); + } m_inst->AppendComment(ss.GetString()); } } diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index 0e203fe43a79..d8279e44e14a 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -34,6 +34,13 @@ ResolveRendezvousAddress(Process *process) addr_t info_addr; Error error; + if (!process) + { + if (log) + log->Printf ("%s null process provided", __FUNCTION__); + return LLDB_INVALID_ADDRESS; + } + // Try to get it from our process. This might be a remote process and might // grab it via some remote-specific mechanism. info_location = process->GetImageInfoAddress(); @@ -43,7 +50,7 @@ ResolveRendezvousAddress(Process *process) // If the process fails to return an address, fall back to seeing if the local object file can help us find it. if (info_location == LLDB_INVALID_ADDRESS) { - Target *target = process ? &process->GetTarget() : nullptr; + Target *target = &process->GetTarget(); if (target) { ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); @@ -70,6 +77,9 @@ ResolveRendezvousAddress(Process *process) return LLDB_INVALID_ADDRESS; } + if (log) + log->Printf ("%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64, __FUNCTION__, process->GetAddressByteSize(), info_location); + info_addr = process->ReadPointerFromMemory(info_location, error); if (error.Fail()) { @@ -193,7 +203,7 @@ DYLDRendezvous::UpdateSOEntries() // state and take a snapshot of the currently loaded images. if (m_current.state == eAdd || m_current.state == eDelete) { - assert(m_previous.state == eConsistent); + assert(m_previous.state == eConsistent || (m_previous.state == eAdd && m_current.state == eDelete)); m_soentries.clear(); m_added_soentries.clear(); m_removed_soentries.clear(); @@ -320,23 +330,11 @@ DYLDRendezvous::ReadStringFromMemory(addr_t addr) { std::string str; Error error; - size_t size; - char c; if (addr == LLDB_INVALID_ADDRESS) return std::string(); - for (;;) { - size = m_process->DoReadMemory(addr, &c, 1, error); - if (size != 1 || error.Fail()) - return std::string(); - if (c == 0) - break; - else { - str.push_back(c); - addr++; - } - } + m_process->ReadCStringFromMemory(addr, str, error); return str; } diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 549e5f9b5345..6b0b6f5cc8b8 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -111,27 +111,88 @@ DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() void DynamicLoaderPOSIXDYLD::DidAttach() { - ModuleSP executable; - addr_t load_offset; + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID); m_auxv.reset(new AuxVector(m_process)); + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reloaded auxv data", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID); - executable = GetTargetExecutable(); - load_offset = ComputeLoadOffset(); + ModuleSP executable_sp = GetTargetExecutable(); + ModuleSpec process_module_spec; + if (GetProcessModuleSpec(process_module_spec)) + { + if (executable_sp == nullptr || !executable_sp->MatchesModuleSpec(process_module_spec)) + { + executable_sp.reset(new Module(process_module_spec)); + assert(m_process != nullptr); + m_process->GetTarget().SetExecutableModule(executable_sp, false); + } + } - if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) + addr_t load_offset = ComputeLoadOffset(); + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " executable '%s', load_offset 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, executable_sp ? executable_sp->GetFileSpec().GetPath().c_str () : "", load_offset); + + + if (executable_sp && load_offset != LLDB_INVALID_ADDRESS) { ModuleList module_list; - module_list.Append(executable); - UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset); - LoadAllCurrentModules(); + + module_list.Append(executable_sp); + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " added executable '%s' to module load list", + __FUNCTION__, + m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, + executable_sp->GetFileSpec().GetPath().c_str ()); + + UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset); + + // When attaching to a target, there are two possible states: + // (1) We already crossed the entry point and therefore the rendezvous + // structure is ready to be used and we can load the list of modules + // and place the rendezvous breakpoint. + // (2) We didn't cross the entry point yet, so these structures are not + // ready; we should behave as if we just launched the target and + // call ProbeEntry(). This will place a breakpoint on the entry + // point which itself will be hit after the rendezvous structure is + // set up and will perform actions described in (1). + if (m_rendezvous.Resolve()) + { + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64 " rendezvous could resolve: attach assuming dynamic loader info is available now", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID); + LoadAllCurrentModules(); + SetRendezvousBreakpoint(); + } + else + { + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64 " rendezvous could not yet resolve: adding breakpoint to catch future rendezvous setup", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID); + ProbeEntry(); + } + m_process->GetTarget().ModulesDidLoad(module_list); + if (log) + { + log->Printf ("DynamicLoaderPOSIXDYLD::%s told the target about the modules that loaded:", __FUNCTION__); + for (auto module_sp : module_list.Modules ()) + { + log->Printf ("-- [module] %s (pid %" PRIu64 ")", + module_sp ? module_sp->GetFileSpec().GetPath().c_str () : "", + m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID); + } + } } } void DynamicLoaderPOSIXDYLD::DidLaunch() { + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s()", __FUNCTION__); + ModuleSP executable; addr_t load_offset; @@ -145,7 +206,11 @@ DynamicLoaderPOSIXDYLD::DidLaunch() ModuleList module_list; module_list.Append(executable); UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset); + + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", __FUNCTION__); ProbeEntry(); + m_process->GetTarget().ModulesDidLoad(module_list); } } @@ -187,15 +252,28 @@ DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module) void DynamicLoaderPOSIXDYLD::ProbeEntry() { - Breakpoint *entry_break; - addr_t entry; + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) + const addr_t entry = GetEntryPoint(); + if (entry == LLDB_INVALID_ADDRESS) + { + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " GetEntryPoint() returned no address, not setting entry breakpoint", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID); return; - - entry_break = m_process->GetTarget().CreateBreakpoint(entry, true, false).get(); - entry_break->SetCallback(EntryBreakpointHit, this, true); - entry_break->SetBreakpointKind("shared-library-event"); + } + + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " GetEntryPoint() returned address 0x%" PRIx64 ", setting entry breakpoint", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, entry); + + if (m_process) + { + Breakpoint *const entry_break = m_process->GetTarget().CreateBreakpoint(entry, true, false).get(); + entry_break->SetCallback(EntryBreakpointHit, this, true); + entry_break->SetBreakpointKind("shared-library-event"); + + // Shoudn't hit this more than once. + entry_break->SetOneShot (true); + } } // The runtime linker has run and initialized the rendezvous structure once the @@ -210,9 +288,40 @@ DynamicLoaderPOSIXDYLD::EntryBreakpointHit(void *baton, user_id_t break_id, user_id_t break_loc_id) { - DynamicLoaderPOSIXDYLD* dyld_instance; + assert(baton && "null baton"); + if (!baton) + return false; + + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + DynamicLoaderPOSIXDYLD *const dyld_instance = static_cast(baton); + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, __FUNCTION__, dyld_instance->m_process ? dyld_instance->m_process->GetID () : LLDB_INVALID_PROCESS_ID); + + // Disable the breakpoint --- if a stop happens right after this, which we've seen on occasion, we don't + // want the breakpoint stepping thread-plan logic to show a breakpoint instruction at the disassembled + // entry point to the program. Disabling it prevents it. (One-shot is not enough - one-shot removal logic + // only happens after the breakpoint goes public, which wasn't happening in our scenario). + if (dyld_instance->m_process) + { + BreakpointSP breakpoint_sp = dyld_instance->m_process->GetTarget().GetBreakpointByID (break_id); + if (breakpoint_sp) + { + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " disabling breakpoint id %" PRIu64, __FUNCTION__, dyld_instance->m_process->GetID (), break_id); + breakpoint_sp->SetEnabled (false); + } + else + { + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " failed to find breakpoint for breakpoint id %" PRIu64, __FUNCTION__, dyld_instance->m_process->GetID (), break_id); + } + } + else + { + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s breakpoint id %" PRIu64 " no Process instance! Cannot disable breakpoint", __FUNCTION__, break_id); + } - dyld_instance = static_cast(baton); dyld_instance->LoadAllCurrentModules(); dyld_instance->SetRendezvousBreakpoint(); return false; // Continue running. @@ -221,16 +330,25 @@ DynamicLoaderPOSIXDYLD::EntryBreakpointHit(void *baton, void DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() { + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + addr_t break_addr = m_rendezvous.GetBreakAddress(); Target &target = m_process->GetTarget(); if (m_dyld_bid == LLDB_INVALID_BREAK_ID) { + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " setting rendezvous break address at 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, break_addr); Breakpoint *dyld_break = target.CreateBreakpoint (break_addr, true, false).get(); dyld_break->SetCallback(RendezvousBreakpointHit, this, true); dyld_break->SetBreakpointKind ("shared-library-event"); m_dyld_bid = dyld_break->GetID(); } + else + { + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reusing break id %" PRIu32 ", address at 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, m_dyld_bid, break_addr); + } // Make sure our breakpoint is at the right address. assert (target.GetBreakpointByID(m_dyld_bid)->FindLocationByAddress(break_addr)->GetBreakpoint().GetID() == m_dyld_bid); @@ -242,13 +360,22 @@ DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit(void *baton, user_id_t break_id, user_id_t break_loc_id) { - DynamicLoaderPOSIXDYLD* dyld_instance; + assert (baton && "null baton"); + if (!baton) + return false; + + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + DynamicLoaderPOSIXDYLD *const dyld_instance = static_cast(baton); + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, __FUNCTION__, dyld_instance->m_process ? dyld_instance->m_process->GetID () : LLDB_INVALID_PROCESS_ID); - dyld_instance = static_cast(baton); dyld_instance->RefreshModules(); // Return true to stop the target, false to just let the target run. - return dyld_instance->GetStopWhenImagesChange(); + const bool stop_when_images_change = dyld_instance->GetStopWhenImagesChange(); + if (log) + log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " stop_when_images_change=%s", __FUNCTION__, dyld_instance->m_process ? dyld_instance->m_process->GetID () : LLDB_INVALID_PROCESS_ID, stop_when_images_change ? "true" : "false"); + return stop_when_images_change; } void @@ -439,6 +566,13 @@ DynamicLoaderPOSIXDYLD::GetEntryPoint() return LLDB_INVALID_ADDRESS; m_entry_point = static_cast(I->value); + + const ArchSpec &arch = m_process->GetTarget().GetArchitecture(); + + // On ppc64, the entry point is actually a descriptor. Dereference it. + if (arch.GetMachine() == llvm::Triple::ppc64) + m_entry_point = ReadUnsignedIntWithSizeInBytes(m_entry_point, 8); + return m_entry_point; } @@ -487,3 +621,18 @@ DynamicLoaderPOSIXDYLD::GetThreadLocalData (const lldb::ModuleSP module, const l return tls_block; } + +bool +DynamicLoaderPOSIXDYLD::GetProcessModuleSpec (ModuleSpec& module_spec) +{ + if (m_process == nullptr) + return false; + + auto& target = m_process->GetTarget (); + ProcessInstanceInfo process_info; + if (!target.GetPlatform ()->GetProcessInfo (m_process->GetID (), process_info)) + return false; + + module_spec = ModuleSpec (process_info.GetExecutableFile (), process_info.GetArchitecture ()); + return true; +} diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h index 9ced5da8a015..747ff3f2be36 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h @@ -168,6 +168,10 @@ protected: lldb::addr_t GetEntryPoint(); + /// Loads ModuleSpec data from inferior process. + bool + GetProcessModuleSpec(lldb_private::ModuleSpec& module_spec); + private: DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD); }; diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index fa8681ed69fe..bc358a985248 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -9873,12 +9873,14 @@ EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding en if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0)) return false; } +#if 0 // unreachable because if true else { // R[d] = 1; if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1)) return false; } +#endif // unreachable because if true } return true; } diff --git a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp new file mode 100644 index 000000000000..96754ff78787 --- /dev/null +++ b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp @@ -0,0 +1,314 @@ +//===-- AddressSanitizerRuntime.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "AddressSanitizerRuntime.h" + +#include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/InstrumentationRuntimeStopInfo.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" + +using namespace lldb; +using namespace lldb_private; + +lldb::InstrumentationRuntimeSP +AddressSanitizerRuntime::CreateInstance (const lldb::ProcessSP &process_sp) +{ + return InstrumentationRuntimeSP(new AddressSanitizerRuntime(process_sp)); +} + +void +AddressSanitizerRuntime::Initialize() +{ + PluginManager::RegisterPlugin (GetPluginNameStatic(), + "AddressSanitizer instrumentation runtime plugin.", + CreateInstance, + GetTypeStatic); +} + +void +AddressSanitizerRuntime::Terminate() +{ + PluginManager::UnregisterPlugin (CreateInstance); +} + +lldb_private::ConstString +AddressSanitizerRuntime::GetPluginNameStatic() +{ + return ConstString("AddressSanitizer"); +} + +lldb::InstrumentationRuntimeType +AddressSanitizerRuntime::GetTypeStatic() +{ + return eInstrumentationRuntimeTypeAddressSanitizer; +} + +AddressSanitizerRuntime::AddressSanitizerRuntime(const ProcessSP &process_sp) : + m_is_active(false), + m_runtime_module(), + m_process(process_sp), + m_breakpoint_id(0) +{ +} + +AddressSanitizerRuntime::~AddressSanitizerRuntime() +{ + Deactivate(); +} + +bool ModuleContainsASanRuntime(Module * module) +{ + SymbolContextList sc_list; + const bool include_symbols = true; + const bool append = true; + const bool include_inlines = true; + + size_t num_matches = module->FindFunctions(ConstString("__asan_get_alloc_stack"), NULL, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list); + + return num_matches > 0; +} + +void +AddressSanitizerRuntime::ModulesDidLoad(lldb_private::ModuleList &module_list) +{ + if (IsActive()) + return; + + if (m_runtime_module) { + Activate(); + return; + } + + Mutex::Locker modules_locker(module_list.GetMutex()); + const size_t num_modules = module_list.GetSize(); + for (size_t i = 0; i < num_modules; ++i) + { + Module *module_pointer = module_list.GetModulePointerAtIndexUnlocked(i); + const FileSpec & file_spec = module_pointer->GetFileSpec(); + if (! file_spec) + continue; + + static RegularExpression g_asan_runtime_regex("libclang_rt.asan_(.*)_dynamic\\.dylib"); + if (g_asan_runtime_regex.Execute (file_spec.GetFilename().GetCString()) || module_pointer->IsExecutable()) + { + if (ModuleContainsASanRuntime(module_pointer)) + { + m_runtime_module = module_pointer->shared_from_this(); + Activate(); + return; + } + } + } +} + +bool +AddressSanitizerRuntime::IsActive() +{ + return m_is_active; +} + +#define RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC 2*1000*1000 + +const char * +address_sanitizer_retrieve_report_data_command = R"( + struct { + int present; + void *pc, *bp, *sp, *address; + int access_type; + size_t access_size; + const char *description; + } t; + + t.present = ((int (*) ())__asan_report_present)(); + t.pc = ((void * (*) ())__asan_get_report_pc)(); + /* commented out because rdar://problem/18533301 + t.bp = ((void * (*) ())__asan_get_report_bp)(); + t.sp = ((void * (*) ())__asan_get_report_sp)(); + */ + t.address = ((void * (*) ())__asan_get_report_address)(); + t.description = ((const char * (*) ())__asan_get_report_description)(); + t.access_type = ((int (*) ())__asan_get_report_access_type)(); + t.access_size = ((size_t (*) ())__asan_get_report_access_size)(); + + t; +)"; + +StructuredData::ObjectSP +AddressSanitizerRuntime::RetrieveReportData() +{ + ThreadSP thread_sp = m_process->GetThreadList().GetSelectedThread(); + StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); + + if (!frame_sp) + return StructuredData::ObjectSP(); + + EvaluateExpressionOptions options; + options.SetUnwindOnError(true); + options.SetTryAllThreads(true); + options.SetStopOthers(true); + options.SetIgnoreBreakpoints(true); + options.SetTimeoutUsec(RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC); + + ValueObjectSP return_value_sp; + if (m_process->GetTarget().EvaluateExpression(address_sanitizer_retrieve_report_data_command, frame_sp.get(), return_value_sp, options) != eExpressionCompleted) + return StructuredData::ObjectSP(); + + int present = return_value_sp->GetValueForExpressionPath(".present")->GetValueAsUnsigned(0); + if (present != 1) + return StructuredData::ObjectSP(); + + addr_t pc = return_value_sp->GetValueForExpressionPath(".pc")->GetValueAsUnsigned(0); + addr_t bp = return_value_sp->GetValueForExpressionPath(".bp")->GetValueAsUnsigned(0); + addr_t sp = return_value_sp->GetValueForExpressionPath(".sp")->GetValueAsUnsigned(0); + addr_t address = return_value_sp->GetValueForExpressionPath(".address")->GetValueAsUnsigned(0); + addr_t access_type = return_value_sp->GetValueForExpressionPath(".access_type")->GetValueAsUnsigned(0); + addr_t access_size = return_value_sp->GetValueForExpressionPath(".access_size")->GetValueAsUnsigned(0); + addr_t description_ptr = return_value_sp->GetValueForExpressionPath(".description")->GetValueAsUnsigned(0); + std::string description; + Error error; + m_process->ReadCStringFromMemory(description_ptr, description, error); + + StructuredData::Dictionary *dict = new StructuredData::Dictionary(); + dict->AddStringItem("instrumentation_class", "AddressSanitizer"); + dict->AddStringItem("stop_type", "fatal_error"); + dict->AddIntegerItem("pc", pc); + dict->AddIntegerItem("bp", bp); + dict->AddIntegerItem("sp", sp); + dict->AddIntegerItem("address", address); + dict->AddIntegerItem("access_type", access_type); + dict->AddIntegerItem("access_size", access_size); + dict->AddStringItem("description", description); + + return StructuredData::ObjectSP(dict); +} + +std::string +AddressSanitizerRuntime::FormatDescription(StructuredData::ObjectSP report) +{ + std::string description = report->GetAsDictionary()->GetValueForKey("description")->GetAsString()->GetValue(); + if (description == "heap-use-after-free") { + return "Use of deallocated memory detected"; + } else if (description == "heap-buffer-overflow") { + return "Heap buffer overflow detected"; + } else if (description == "stack-buffer-underflow") { + return "Stack buffer underflow detected"; + } else if (description == "initialization-order-fiasco") { + return "Initialization order problem detected"; + } else if (description == "stack-buffer-overflow") { + return "Stack buffer overflow detected"; + } else if (description == "stack-use-after-return") { + return "Use of returned stack memory detected"; + } else if (description == "use-after-poison") { + return "Use of poisoned memory detected"; + } else if (description == "container-overflow") { + return "Container overflow detected"; + } else if (description == "stack-use-after-scope") { + return "Use of out-of-scope stack memory detected"; + } else if (description == "global-buffer-overflow") { + return "Global buffer overflow detected"; + } else if (description == "unknown-crash") { + return "Invalid memory access detected"; + } + + // for unknown report codes just show the code + return description; +} + +bool +AddressSanitizerRuntime::NotifyBreakpointHit(void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) +{ + assert (baton && "null baton"); + if (!baton) + return false; + + AddressSanitizerRuntime *const instance = static_cast(baton); + + StructuredData::ObjectSP report = instance->RetrieveReportData(); + std::string description; + if (report) { + description = instance->FormatDescription(report); + } + ThreadSP thread = context->exe_ctx_ref.GetThreadSP(); + thread->SetStopInfo(InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(*thread, description.c_str(), report)); + + if (instance->m_process) + { + StreamFileSP stream_sp (instance->m_process->GetTarget().GetDebugger().GetOutputFile()); + if (stream_sp) + { + stream_sp->Printf ("AddressSanitizer report breakpoint hit. Use 'thread info -s' to get extended information about the report.\n"); + } + } + // Return true to stop the target, false to just let the target run. + return true; +} + +void +AddressSanitizerRuntime::Activate() +{ + if (m_is_active) + return; + + ConstString symbol_name ("__asan::AsanDie()"); + const Symbol *symbol = m_runtime_module->FindFirstSymbolWithNameAndType (symbol_name, eSymbolTypeCode); + + if (symbol == NULL) + return; + + if (!symbol->GetAddress().IsValid()) + return; + + Target &target = m_process->GetTarget(); + addr_t symbol_address = symbol->GetAddress().GetOpcodeLoadAddress(&target); + + if (symbol_address == LLDB_INVALID_ADDRESS) + return; + + bool internal = true; + bool hardware = false; + Breakpoint *breakpoint = m_process->GetTarget().CreateBreakpoint(symbol_address, internal, hardware).get(); + breakpoint->SetCallback (AddressSanitizerRuntime::NotifyBreakpointHit, this, true); + breakpoint->SetBreakpointKind ("address-sanitizer-report"); + m_breakpoint_id = breakpoint->GetID(); + + if (m_process) + { + StreamFileSP stream_sp (m_process->GetTarget().GetDebugger().GetOutputFile()); + if (stream_sp) + { + stream_sp->Printf ("AddressSanitizer debugger support is active. Memory error breakpoint has been installed and you can now use the 'memory history' command.\n"); + } + } + + m_is_active = true; +} + +void +AddressSanitizerRuntime::Deactivate() +{ + if (m_breakpoint_id != LLDB_INVALID_BREAK_ID) + { + m_process->GetTarget().RemoveBreakpointByID(m_breakpoint_id); + m_breakpoint_id = LLDB_INVALID_BREAK_ID; + } + m_is_active = false; +} diff --git a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h new file mode 100644 index 000000000000..69c134cbedaf --- /dev/null +++ b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h @@ -0,0 +1,86 @@ +//===-- AddressSanitizerRuntime.h -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_AddressSanitizerRuntime_h_ +#define liblldb_AddressSanitizerRuntime_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Target/ABI.h" +#include "lldb/Target/InstrumentationRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Core/StructuredData.h" + +namespace lldb_private { + +class AddressSanitizerRuntime : public lldb_private::InstrumentationRuntime +{ +public: + + static lldb::InstrumentationRuntimeSP + CreateInstance (const lldb::ProcessSP &process_sp); + + static void + Initialize(); + + static void + Terminate(); + + static lldb_private::ConstString + GetPluginNameStatic(); + + static lldb::InstrumentationRuntimeType + GetTypeStatic(); + + virtual + ~AddressSanitizerRuntime(); + + virtual lldb_private::ConstString + GetPluginName() { return GetPluginNameStatic(); } + + virtual lldb::InstrumentationRuntimeType + GetType() { return GetTypeStatic(); } + + virtual uint32_t + GetPluginVersion() { return 1; } + + virtual void + ModulesDidLoad(lldb_private::ModuleList &module_list); + + virtual bool + IsActive(); + +private: + + AddressSanitizerRuntime(const lldb::ProcessSP &process_sp); + + void + Activate(); + + void + Deactivate(); + + static bool + NotifyBreakpointHit(void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id); + + StructuredData::ObjectSP + RetrieveReportData(); + + std::string + FormatDescription(StructuredData::ObjectSP report); + + bool m_is_active; + lldb::ModuleSP m_runtime_module; + lldb::ProcessSP m_process; + lldb::user_id_t m_breakpoint_id; + +}; + +} // namespace lldb_private + +#endif // liblldb_InstrumentationRuntime_h_ diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp index 905984d33410..cd303cb0768f 100644 --- a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp +++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp @@ -36,21 +36,24 @@ typedef enum JIT_UNREGISTER_FN } jit_actions_t; +#pragma pack(push, 4) +template struct jit_code_entry { - struct jit_code_entry *next_entry; - struct jit_code_entry *prev_entry; - const char *symfile_addr; + ptr_t next_entry; // pointer + ptr_t prev_entry; // pointer + ptr_t symfile_addr; // pointer uint64_t symfile_size; }; - +template struct jit_descriptor { uint32_t version; uint32_t action_flag; // Values are jit_action_t - struct jit_code_entry *relevant_entry; - struct jit_code_entry *first_entry; + ptr_t relevant_entry; // pointer + ptr_t first_entry; // pointer }; +#pragma pack(pop) JITLoaderGDB::JITLoaderGDB (lldb_private::Process *process) : JITLoader(process), @@ -197,6 +200,17 @@ static void updateSectionLoadAddress(const SectionList §ion_list, bool JITLoaderGDB::ReadJITDescriptor(bool all_entries) +{ + Target &target = m_process->GetTarget(); + if (target.GetArchitecture().GetAddressByteSize() == 8) + return ReadJITDescriptorImpl(all_entries); + else + return ReadJITDescriptorImpl(all_entries); +} + +template +bool +JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) { if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS) return false; @@ -205,7 +219,7 @@ JITLoaderGDB::ReadJITDescriptor(bool all_entries) Target &target = m_process->GetTarget(); ModuleList &module_list = target.GetImages(); - jit_descriptor jit_desc; + jit_descriptor jit_desc; const size_t jit_desc_size = sizeof(jit_desc); Error error; size_t bytes_read = m_process->DoReadMemory( @@ -228,7 +242,7 @@ JITLoaderGDB::ReadJITDescriptor(bool all_entries) while (jit_relevant_entry != 0) { - jit_code_entry jit_entry; + jit_code_entry jit_entry; const size_t jit_entry_size = sizeof(jit_entry); bytes_read = m_process->DoReadMemory(jit_relevant_entry, &jit_entry, jit_entry_size, error); if (bytes_read != jit_entry_size || !error.Success()) diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.h b/source/Plugins/JITLoader/GDB/JITLoaderGDB.h index 5fa66b874972..bfa1721d3349 100644 --- a/source/Plugins/JITLoader/GDB/JITLoaderGDB.h +++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.h @@ -81,6 +81,10 @@ private: bool ReadJITDescriptor(bool all_entries); + template + bool + ReadJITDescriptorImpl(bool all_entries); + static bool JITDebugBreakpointHit(void *baton, lldb_private::StoppointCallbackContext *context, diff --git a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp new file mode 100644 index 000000000000..c7c64ed54d87 --- /dev/null +++ b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp @@ -0,0 +1,183 @@ +//===-- MemoryHistoryASan.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MemoryHistoryASan.h" + +#include "lldb/Target/MemoryHistory.h" + +#include "lldb/lldb-private.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Target/ThreadList.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Core/Module.h" +#include "Plugins/Process/Utility/HistoryThread.h" +#include "lldb/Core/ValueObject.h" + +using namespace lldb; +using namespace lldb_private; + +MemoryHistorySP +MemoryHistoryASan::CreateInstance (const ProcessSP &process_sp) +{ + if (!process_sp.get()) + return NULL; + + Target & target = process_sp->GetTarget(); + + bool found_asan_runtime = false; + + const ModuleList &target_modules = target.GetImages(); + Mutex::Locker modules_locker(target_modules.GetMutex()); + const size_t num_modules = target_modules.GetSize(); + for (size_t i = 0; i < num_modules; ++i) + { + Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked(i); + + SymbolContextList sc_list; + const bool include_symbols = true; + const bool append = true; + const bool include_inlines = true; + + size_t num_matches = module_pointer->FindFunctions(ConstString("__asan_get_alloc_stack"), NULL, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list); + + if (num_matches) + { + found_asan_runtime = true; + break; + } + } + + if (! found_asan_runtime) + return MemoryHistorySP(); + + return MemoryHistorySP(new MemoryHistoryASan(process_sp)); +} + +void +MemoryHistoryASan::Initialize() +{ + PluginManager::RegisterPlugin (GetPluginNameStatic(), + "ASan memory history provider.", + CreateInstance); +} + +void +MemoryHistoryASan::Terminate() +{ + PluginManager::UnregisterPlugin (CreateInstance); +} + + +ConstString +MemoryHistoryASan::GetPluginNameStatic() +{ + static ConstString g_name("asan"); + return g_name; +} + +MemoryHistoryASan::MemoryHistoryASan(const ProcessSP &process_sp) +{ + this->m_process_sp = process_sp; +} + +const char * +memory_history_asan_command_format = R"( + struct t { + void *alloc_trace[256]; + size_t alloc_count; + int alloc_tid; + + void *free_trace[256]; + size_t free_count; + int free_tid; + } t; + + t.alloc_count = ((size_t (*) (void *, void **, size_t, int *))__asan_get_alloc_stack)((void *)0x%)" PRIx64 R"(, t.alloc_trace, 256, &t.alloc_tid); + t.free_count = ((size_t (*) (void *, void **, size_t, int *))__asan_get_free_stack)((void *)0x%)" PRIx64 R"(, t.free_trace, 256, &t.free_tid); + + t; +)"; + +static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, ValueObjectSP return_value_sp, const char *type, const char *thread_name, HistoryThreads & result) +{ + std::string count_path = "." + std::string(type) + "_count"; + std::string tid_path = "." + std::string(type) + "_tid"; + std::string trace_path = "." + std::string(type) + "_trace"; + + int count = return_value_sp->GetValueForExpressionPath(count_path.c_str())->GetValueAsUnsigned(0); + tid_t tid = return_value_sp->GetValueForExpressionPath(tid_path.c_str())->GetValueAsUnsigned(0); + + if (count <= 0) + return; + + ValueObjectSP trace_sp = return_value_sp->GetValueForExpressionPath(trace_path.c_str()); + + std::vector pcs; + for (int i = 0; i < count; i++) + { + addr_t pc = trace_sp->GetChildAtIndex(i, true)->GetValueAsUnsigned(0); + if (pc == 0 || pc == 1 || pc == LLDB_INVALID_ADDRESS) + continue; + pcs.push_back(pc); + } + + HistoryThread *history_thread = new HistoryThread(*process_sp, tid, pcs, 0, false); + ThreadSP new_thread_sp(history_thread); + // let's use thread name for the type of history thread, since history threads don't have names anyway + history_thread->SetThreadName(thread_name); + // Save this in the Process' ExtendedThreadList so a strong pointer retains the object + process_sp->GetExtendedThreadList().AddThread (new_thread_sp); + result.push_back(new_thread_sp); +} + +#define GET_STACK_FUNCTION_TIMEOUT_USEC 2*1000*1000 + +HistoryThreads +MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address) +{ + ProcessSP process_sp = m_process_sp; + ThreadSP thread_sp = m_process_sp->GetThreadList().GetSelectedThread(); + StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); + + if (!frame_sp) + { + return HistoryThreads(); + } + + ExecutionContext exe_ctx (frame_sp); + ValueObjectSP return_value_sp; + StreamString expr; + expr.Printf(memory_history_asan_command_format, address, address); + + EvaluateExpressionOptions options; + options.SetUnwindOnError(true); + options.SetTryAllThreads(true); + options.SetStopOthers(true); + options.SetIgnoreBreakpoints(true); + options.SetTimeoutUsec(GET_STACK_FUNCTION_TIMEOUT_USEC); + + if (m_process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), return_value_sp, options) != eExpressionCompleted) + { + return HistoryThreads(); + } + if (!return_value_sp) + { + return HistoryThreads(); + } + + HistoryThreads result; + + CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc", "Memory allocated at", result); + CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free", "Memory deallocated at", result); + + return result; +} diff --git a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h new file mode 100644 index 000000000000..5307e0b34081 --- /dev/null +++ b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h @@ -0,0 +1,62 @@ +//===-- MemoryHistoryASan.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_MemoryHistoryASan_h_ +#define liblldb_MemoryHistoryASan_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Target/ABI.h" +#include "lldb/Target/MemoryHistory.h" +#include "lldb/Target/Process.h" + +namespace lldb_private { + +class MemoryHistoryASan : public lldb_private::MemoryHistory +{ +public: + + static lldb::MemoryHistorySP + CreateInstance (const lldb::ProcessSP &process_sp); + + static void + Initialize(); + + static void + Terminate(); + + static lldb_private::ConstString + GetPluginNameStatic(); + + virtual + ~MemoryHistoryASan () {} + + virtual lldb_private::ConstString + GetPluginName() { return GetPluginNameStatic(); } + + virtual uint32_t + GetPluginVersion() { return 1; } + + virtual lldb_private::HistoryThreads + GetHistoryThreads(lldb::addr_t address); + +private: + + MemoryHistoryASan(const lldb::ProcessSP &process_sp); + + lldb::ProcessSP m_process_sp; + +}; + +} // namespace lldb_private + +#endif // liblldb_MemoryHistoryASan_h_ diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp index 0263c23ce307..1e2a0c721ff6 100644 --- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -9,7 +9,7 @@ #include "ObjectContainerBSDArchive.h" -#ifdef _WIN32 +#if defined(_WIN32) || defined(__ANDROID_NDK__) // Defines from ar, missing on Windows #define ARMAG "!\n" #define SARMAG 8 diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp index f027294b7c57..12392c24407b 100644 --- a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp +++ b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp @@ -173,6 +173,12 @@ ELFHeader::GetRelocationJumpSlotType() const default: assert(false && "architecture not supported"); break; + case EM_PPC: + slot = R_PPC_JMP_SLOT; + break; + case EM_PPC64: + slot = R_PPC64_JMP_SLOT; + break; case EM_386: case EM_486: slot = R_386_JUMP_SLOT; @@ -189,6 +195,9 @@ ELFHeader::GetRelocationJumpSlotType() const case EM_AARCH64: slot = R_AARCH64_JUMP_SLOT; break; + case EM_MIPS: + slot = R_MIPS_JUMP_SLOT; + break; } return slot; diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index d86aee78947f..e7bf20e18008 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -267,10 +267,14 @@ kalimbaVariantFromElfFlags(const elf::elf_word e_flags) { // TODO(mg11) Support more variants case 10: - kal_arch_variant = 3; + kal_arch_variant = llvm::Triple::KalimbaSubArch_v3; break; case 14: - kal_arch_variant = 4; + kal_arch_variant = llvm::Triple::KalimbaSubArch_v4; + break; + case 17: + case 20: + kal_arch_variant = llvm::Triple::KalimbaSubArch_v5; break; default: break; @@ -287,6 +291,34 @@ subTypeFromElfHeader(const elf::ELFHeader& header) LLDB_INVALID_CPUTYPE; } +//! The kalimba toolchain identifies a code section as being +//! one with the SHT_PROGBITS set in the section sh_type and the top +//! bit in the 32-bit address field set. +static lldb::SectionType +kalimbaSectionType( + const elf::ELFHeader& header, + const elf::ELFSectionHeader& sect_hdr) +{ + if (llvm::ELF::EM_CSR_KALIMBA != header.e_machine) + { + return eSectionTypeOther; + } + + if (llvm::ELF::SHT_NOBITS == sect_hdr.sh_type) + { + return eSectionTypeZeroFill; + } + + if (llvm::ELF::SHT_PROGBITS == sect_hdr.sh_type) + { + const lldb::addr_t KAL_CODE_BIT = 1 << 31; + return KAL_CODE_BIT & sect_hdr.sh_addr ? + eSectionTypeCode : eSectionTypeData; + } + + return eSectionTypeOther; +} + // Arbitrary constant used as UUID prefix for core files. const uint32_t ObjectFileELF::g_core_uuid_magic(0xE210C); @@ -826,6 +858,38 @@ ObjectFileELF::GetAddressByteSize() const return m_data.GetAddressByteSize(); } +// Top 16 bits of the `Symbol` flags are available. +#define ARM_ELF_SYM_IS_THUMB (1 << 16) + +AddressClass +ObjectFileELF::GetAddressClass (addr_t file_addr) +{ + auto res = ObjectFile::GetAddressClass (file_addr); + + if (res != eAddressClassCode) + return res; + + ArchSpec arch_spec; + GetArchitecture(arch_spec); + if (arch_spec.GetMachine() != llvm::Triple::arm) + return res; + + auto symtab = GetSymtab(); + if (symtab == nullptr) + return res; + + auto symbol = symtab->FindSymbolContainingFileAddress(file_addr); + if (symbol == nullptr) + return res; + + // Thumb symbols have the lower bit set in the flags field so we just check + // for that. + if (symbol->GetFlags() & ARM_ELF_SYM_IS_THUMB) + res = eAddressClassCodeAlternateISA; + + return res; +} + size_t ObjectFileELF::SectionIndex(const SectionHeaderCollIter &I) { @@ -1560,6 +1624,20 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list) break; } + if (eSectionTypeOther == sect_type) + { + // the kalimba toolchain assumes that ELF section names are free-form. It does + // supports linkscripts which (can) give rise to various arbitarily named + // sections being "Code" or "Data". + sect_type = kalimbaSectionType(m_header, header); + } + + const uint32_t target_bytes_size = + (eSectionTypeData == sect_type || eSectionTypeZeroFill == sect_type) ? + m_arch_spec.GetDataByteSize() : + eSectionTypeCode == sect_type ? + m_arch_spec.GetCodeByteSize() : 1; + elf::elf_xword log2align = (header.sh_addralign==0) ? 0 : llvm::Log2_64(header.sh_addralign); @@ -1573,7 +1651,8 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list) header.sh_offset, // Offset of this section in the file. file_size, // Size of the section as found in the file. log2align, // Alignment of the section - header.sh_flags)); // Flags for this section. + header.sh_flags, // Flags for this section. + target_bytes_size));// Number of host bytes per target byte if (is_thread_specific) section_sp->SetIsThreadSpecific (is_thread_specific); @@ -1645,6 +1724,7 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, static ConstString rodata1_section_name(".rodata1"); static ConstString data2_section_name(".data1"); static ConstString bss_section_name(".bss"); + static ConstString opd_section_name(".opd"); // For ppc64 //StreamFile strm(stdout, false); unsigned i; @@ -1746,6 +1826,48 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, } } + ArchSpec arch; + int64_t symbol_value_offset = 0; + uint32_t additional_flags = 0; + + if (GetArchitecture(arch) && + arch.GetMachine() == llvm::Triple::arm) + { + // ELF symbol tables may contain some mapping symbols. They provide + // information about the underlying data. There are three of them + // currently defined: + // $a[.]* - marks an ARM instruction sequence + // $t[.]* - marks a THUMB instruction sequence + // $d[.]* - marks a data item sequence (e.g. lit pool) + // These symbols interfere with normal debugger operations and we + // don't need them. We can drop them here. + + static const llvm::StringRef g_armelf_arm_marker("$a"); + static const llvm::StringRef g_armelf_thumb_marker("$t"); + static const llvm::StringRef g_armelf_data_marker("$d"); + llvm::StringRef symbol_name_ref(symbol_name); + + if (symbol_name && + (symbol_name_ref.startswith(g_armelf_arm_marker) || + symbol_name_ref.startswith(g_armelf_thumb_marker) || + symbol_name_ref.startswith(g_armelf_data_marker))) + continue; + + // THUMB functions have the lower bit of their address set. Fixup + // the actual address and mark the symbol as THUMB. + if (symbol_type == eSymbolTypeCode && symbol.st_value & 1) + { + // Substracting 1 from the address effectively unsets + // the low order bit, which results in the address + // actually pointing to the beginning of the symbol. + // This delta will be used below in conjuction with + // symbol.st_value to produce the final symbol_value + // that we store in the symtab. + symbol_value_offset = -1; + additional_flags = ARM_ELF_SYM_IS_THUMB; + } + } + // If the symbol section we've found has no data (SHT_NOBITS), then check the module section // list. This can happen if we're parsing the debug file and it has no .text section, for example. if (symbol_section_sp && (symbol_section_sp->GetFileSize() == 0)) @@ -1766,12 +1888,15 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, } } - uint64_t symbol_value = symbol.st_value; + // symbol_value_offset may contain 0 for ARM symbols or -1 for + // THUMB symbols. See above for more details. + uint64_t symbol_value = symbol.st_value | symbol_value_offset; if (symbol_section_sp && CalculateType() != ObjectFile::Type::eTypeObjectFile) symbol_value -= symbol_section_sp->GetFileAddress(); bool is_global = symbol.getBinding() == STB_GLOBAL; - uint32_t flags = symbol.st_other << 8 | symbol.st_info; + uint32_t flags = symbol.st_other << 8 | symbol.st_info | additional_flags; bool is_mangled = symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false; + Symbol dc_symbol( i + start_id, // ID is the original symbol table index. symbol_name, // Symbol name. diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 6b036af7aeff..b10dfb532cd0 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -133,6 +133,9 @@ public: virtual uint32_t GetAddressByteSize() const; + virtual lldb::AddressClass + GetAddressClass (lldb::addr_t file_addr); + virtual lldb_private::Symtab * GetSymtab(); diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp index 7aa940a530b4..3b38a5819934 100644 --- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp +++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp @@ -32,7 +32,7 @@ using namespace lldb; using namespace lldb_private; -Platform * +PlatformSP PlatformFreeBSD::CreateInstance (bool force, const lldb_private::ArchSpec *arch) { // The only time we create an instance is when we are creating a remote @@ -84,8 +84,8 @@ PlatformFreeBSD::CreateInstance (bool force, const lldb_private::ArchSpec *arch) } } if (create) - return new PlatformFreeBSD (is_host); - return NULL; + return PlatformSP(new PlatformFreeBSD (is_host)); + return PlatformSP(); } @@ -124,7 +124,7 @@ PlatformFreeBSD::Initialize () // Force a host flag to true for the default platform object. PlatformSP default_platform_sp (new PlatformFreeBSD(true)); default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); - Platform::SetDefaultPlatform (default_platform_sp); + Platform::SetHostPlatform (default_platform_sp); #endif PluginManager::RegisterPlugin(PlatformFreeBSD::GetPluginNameStatic(false), PlatformFreeBSD::GetDescriptionStatic(false), @@ -180,8 +180,7 @@ PlatformFreeBSD::RunShellCommand (const char *command, Error -PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file, - const ArchSpec &exe_arch, +PlatformFreeBSD::ResolveExecutable (const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, const FileSpecList *module_search_paths_ptr) { @@ -189,35 +188,33 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file, // Nothing special to do here, just use the actual file and architecture char exe_path[PATH_MAX]; - FileSpec resolved_exe_file (exe_file); + ModuleSpec resolved_module_spec(module_spec); if (IsHost()) { - // If we have "ls" as the exe_file, resolve the executable location based on + // If we have "ls" as the module_spec's file, resolve the executable location based on // the current path variables - if (!resolved_exe_file.Exists()) + if (!resolved_module_spec.GetFileSpec().Exists()) { - exe_file.GetPath(exe_path, sizeof(exe_path)); - resolved_exe_file.SetFile(exe_path, true); + module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); + resolved_module_spec.GetFileSpec().SetFile(exe_path, true); } - if (!resolved_exe_file.Exists()) - resolved_exe_file.ResolveExecutableLocation (); + if (!resolved_module_spec.GetFileSpec().Exists()) + resolved_module_spec.GetFileSpec().ResolveExecutableLocation (); - if (resolved_exe_file.Exists()) + if (resolved_module_spec.GetFileSpec().Exists()) error.Clear(); else { - exe_file.GetPath(exe_path, sizeof(exe_path)); - error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path); + error.SetErrorStringWithFormat("unable to find executable for '%s'", resolved_module_spec.GetFileSpec().GetPath().c_str()); } } else { if (m_remote_platform_sp) { - error = m_remote_platform_sp->ResolveExecutable (exe_file, - exe_arch, + error = m_remote_platform_sp->ResolveExecutable (module_spec, exe_module_sp, module_search_paths_ptr); } @@ -226,25 +223,24 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file, // We may connect to a process and use the provided executable (Don't use local $PATH). // Resolve any executable within a bundle on MacOSX - Host::ResolveExecutableInBundle (resolved_exe_file); + Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec()); - if (resolved_exe_file.Exists()) { + if (resolved_module_spec.GetFileSpec().Exists()) + { error.Clear(); } else { - exe_file.GetPath(exe_path, sizeof(exe_path)); - error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path); + error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_module_spec.GetFileSpec().GetPath().c_str()); } } } if (error.Success()) { - ModuleSpec module_spec (resolved_exe_file, exe_arch); - if (module_spec.GetArchitecture().IsValid()) + if (resolved_module_spec.GetArchitecture().IsValid()) { - error = ModuleList::GetSharedModule (module_spec, + error = ModuleList::GetSharedModule (resolved_module_spec, exe_module_sp, module_search_paths_ptr, NULL, @@ -254,8 +250,8 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file, { exe_module_sp.reset(); error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s", - exe_file.GetPath().c_str(), - exe_arch.GetArchitectureName()); + resolved_module_spec.GetFileSpec().GetPath().c_str(), + resolved_module_spec.GetArchitecture().GetArchitectureName()); } } else @@ -264,10 +260,9 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file, // the architectures that we should be using (in the correct order) // and see if we can find a match that way StreamString arch_names; - ArchSpec platform_arch; - for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx) + for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx) { - error = ModuleList::GetSharedModule (module_spec, + error = ModuleList::GetSharedModule (resolved_module_spec, exe_module_sp, module_search_paths_ptr, NULL, @@ -283,21 +278,21 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file, if (idx > 0) arch_names.PutCString (", "); - arch_names.PutCString (platform_arch.GetArchitectureName()); + arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName()); } if (error.Fail() || !exe_module_sp) { - if (exe_file.Readable()) + if (resolved_module_spec.GetFileSpec().Readable()) { error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", - exe_file.GetPath().c_str(), + resolved_module_spec.GetFileSpec().GetPath().c_str(), GetPluginName().GetCString(), arch_names.GetString().c_str()); } else { - error.SetErrorStringWithFormat("'%s' is not readable", exe_file.GetPath().c_str()); + error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str()); } } } @@ -326,6 +321,13 @@ PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite trap_opcode_size = sizeof(g_i386_opcode); } break; + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + { + static const uint8_t g_ppc_opcode[] = { 0x7f, 0xe0, 0x00, 0x08 }; + trap_opcode = g_ppc_opcode; + trap_opcode_size = sizeof(g_ppc_opcode); + } } if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) @@ -404,7 +406,7 @@ PlatformFreeBSD::ConnectRemote (Args& args) else { if (!m_remote_platform_sp) - m_remote_platform_sp = Platform::Create ("remote-gdb-server", error); + m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error); if (m_remote_platform_sp) { @@ -507,7 +509,6 @@ lldb::ProcessSP PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info, Debugger &debugger, Target *target, - Listener &listener, Error &error) { lldb::ProcessSP process_sp; @@ -535,7 +536,7 @@ PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info, // The freebsd always currently uses the GDB remote debugger plug-in // so even when debugging locally we are debugging remotely! // Just like the darwin plugin. - process_sp = target->CreateProcess (listener, "gdb-remote", NULL); + process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL); if (process_sp) error = process_sp->Attach (attach_info); @@ -544,7 +545,7 @@ PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info, else { if (m_remote_platform_sp) - process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error); + process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error); else error.SetErrorString ("the platform is not currently connected"); } diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h index 62958a08a9e0..ce3f8cfad976 100644 --- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h +++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h @@ -24,7 +24,7 @@ public: //------------------------------------------------------------ // Class functions //------------------------------------------------------------ - static lldb_private::Platform* + static lldb::PlatformSP CreateInstance (bool force, const lldb_private::ArchSpec *arch); static void @@ -80,8 +80,7 @@ public: uint32_t timeout_sec); virtual lldb_private::Error - ResolveExecutable (const lldb_private::FileSpec &exe_file, - const lldb_private::ArchSpec &arch, + ResolveExecutable (const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, const lldb_private::FileSpecList *module_search_paths_ptr); @@ -135,7 +134,6 @@ public: Attach(lldb_private::ProcessAttachInfo &attach_info, lldb_private::Debugger &debugger, lldb_private::Target *target, - lldb_private::Listener &listener, lldb_private::Error &error); // FreeBSD processes can not be launched by spawning and attaching. diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index cc4c693e1b43..b1be0f5b1fe1 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -15,7 +15,9 @@ // Project includes #include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Host/File.h" #include "lldb/Host/FileCache.h" @@ -330,8 +332,14 @@ PlatformPOSIX::PutFile (const lldb_private::FileSpec& source, error = source_file.Read(buffer_sp->GetBytes(), bytes_read); if (bytes_read) { - WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error); - offset += bytes_read; + const uint64_t bytes_written = WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error); + offset += bytes_written; + if (bytes_written != bytes_read) + { + // We didn't write the correct numbe of bytes, so adjust + // the file position in the source file we are reading from... + source_file.SeekFromStart(offset); + } } else break; @@ -343,6 +351,18 @@ PlatformPOSIX::PutFile (const lldb_private::FileSpec& source, // std::string dst_path (destination.GetPath()); // if (chown_file(this,dst_path.c_str(),uid,gid) != 0) // return Error("unable to perform chown"); + + + uint64_t src_md5[2]; + uint64_t dst_md5[2]; + + if (FileSystem::CalculateMD5 (source, src_md5[0], src_md5[1]) && CalculateMD5 (destination, dst_md5[0], dst_md5[1])) + { + if (src_md5[0] != dst_md5[0] || src_md5[1] != dst_md5[1]) + { + error.SetErrorString("md5 checksum of installed file doesn't match, installation failed"); + } + } return error; } return Platform::PutFile(source,destination,uid,gid); @@ -616,6 +636,18 @@ PlatformPOSIX::GetRemoteOSBuildString (std::string &s) return false; } +size_t +PlatformPOSIX::GetEnvironment (StringList &env) +{ + if (IsRemote()) + { + if (m_remote_platform_sp) + return m_remote_platform_sp->GetEnvironment(env); + return 0; + } + return Host::GetEnvironment(env); +} + bool PlatformPOSIX::GetRemoteOSKernelDescription (std::string &s) { @@ -681,7 +713,7 @@ PlatformPOSIX::ConnectRemote (Args& args) else { if (!m_remote_platform_sp) - m_remote_platform_sp = Platform::Create ("remote-gdb-server", error); + m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error); if (m_remote_platform_sp && error.Success()) error = m_remote_platform_sp->ConnectRemote (args); @@ -739,11 +771,97 @@ PlatformPOSIX::DisconnectRemote () return error; } +Error +PlatformPOSIX::LaunchProcess (ProcessLaunchInfo &launch_info) +{ + Error error; + + if (IsHost()) + { + error = Platform::LaunchProcess (launch_info); + } + else + { + if (m_remote_platform_sp) + error = m_remote_platform_sp->LaunchProcess (launch_info); + else + error.SetErrorString ("the platform is not currently connected"); + } + return error; +} + +lldb::ProcessSP +PlatformPOSIX::Attach (ProcessAttachInfo &attach_info, + Debugger &debugger, + Target *target, + Error &error) +{ + lldb::ProcessSP process_sp; + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); + + if (IsHost()) + { + if (target == NULL) + { + TargetSP new_target_sp; + + error = debugger.GetTargetList().CreateTarget (debugger, + NULL, + NULL, + false, + NULL, + new_target_sp); + target = new_target_sp.get(); + if (log) + log->Printf ("PlatformPOSIX::%s created new target", __FUNCTION__); + } + else + { + error.Clear(); + if (log) + log->Printf ("PlatformPOSIX::%s target already existed, setting target", __FUNCTION__); + } + + if (target && error.Success()) + { + debugger.GetTargetList().SetSelectedTarget(target); + if (log) + { + ModuleSP exe_module_sp = target->GetExecutableModule (); + log->Printf ("PlatformPOSIX::%s set selected target to %p %s", __FUNCTION__, + target, + exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "" ); + } + + + process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), attach_info.GetProcessPluginName(), NULL); + + if (process_sp) + { + // Set UnixSignals appropriately. + process_sp->SetUnixSignals (Host::GetUnixSignals ()); + + ListenerSP listener_sp (new Listener("lldb.PlatformPOSIX.attach.hijack")); + attach_info.SetHijackListener(listener_sp); + process_sp->HijackProcessEvents(listener_sp.get()); + error = process_sp->Attach (attach_info); + } + } + } + else + { + if (m_remote_platform_sp) + process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error); + else + error.SetErrorString ("the platform is not currently connected"); + } + return process_sp; +} + lldb::ProcessSP PlatformPOSIX::DebugProcess (ProcessLaunchInfo &launch_info, Debugger &debugger, Target *target, // Can be NULL, if NULL create a new target, else use existing one - Listener &listener, Error &error) { ProcessSP process_sp; @@ -754,12 +872,12 @@ PlatformPOSIX::DebugProcess (ProcessLaunchInfo &launch_info, // We still need to reap it from lldb but if we let the monitor thread also set the exit status, we set up a // race between debugserver & us for who will find out about the debugged process's death. launch_info.GetFlags().Set(eLaunchFlagDontSetExitStatus); - process_sp = Platform::DebugProcess (launch_info, debugger, target, listener, error); + process_sp = Platform::DebugProcess (launch_info, debugger, target, error); } else { if (m_remote_platform_sp) - process_sp = m_remote_platform_sp->DebugProcess (launch_info, debugger, target, listener, error); + process_sp = m_remote_platform_sp->DebugProcess (launch_info, debugger, target, error); else error.SetErrorString ("the platform is not currently connected"); } diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h index 374e36495d88..aae415e6eefa 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h @@ -31,8 +31,9 @@ public: //------------------------------------------------------------ // lldb_private::Platform functions //------------------------------------------------------------ - virtual lldb_private::OptionGroupOptions* - GetConnectionOptions (lldb_private::CommandInterpreter& interpreter); + virtual lldb_private::OptionGroupOptions + *GetConnectionOptions( + lldb_private::CommandInterpreter &interpreter) override; const char * GetHostname () override; @@ -47,47 +48,47 @@ public: PutFile (const lldb_private::FileSpec& source, const lldb_private::FileSpec& destination, uint32_t uid = UINT32_MAX, - uint32_t gid = UINT32_MAX); + uint32_t gid = UINT32_MAX) override; virtual lldb::user_id_t OpenFile (const lldb_private::FileSpec& file_spec, uint32_t flags, uint32_t mode, - lldb_private::Error &error); + lldb_private::Error &error) override; virtual bool CloseFile (lldb::user_id_t fd, - lldb_private::Error &error); + lldb_private::Error &error) override; virtual uint64_t ReadFile (lldb::user_id_t fd, uint64_t offset, void *dst, uint64_t dst_len, - lldb_private::Error &error); + lldb_private::Error &error) override; virtual uint64_t WriteFile (lldb::user_id_t fd, uint64_t offset, const void* src, uint64_t src_len, - lldb_private::Error &error); + lldb_private::Error &error) override; virtual lldb::user_id_t - GetFileSize (const lldb_private::FileSpec& file_spec); + GetFileSize (const lldb_private::FileSpec& file_spec) override; virtual lldb_private::Error - CreateSymlink(const char *src, const char *dst); + CreateSymlink(const char *src, const char *dst) override; virtual lldb_private::Error GetFile (const lldb_private::FileSpec& source, - const lldb_private::FileSpec& destination); + const lldb_private::FileSpec& destination) override; virtual lldb_private::ConstString - GetRemoteWorkingDirectory(); + GetRemoteWorkingDirectory() override; virtual bool - SetRemoteWorkingDirectory(const lldb_private::ConstString &path); + SetRemoteWorkingDirectory(const lldb_private::ConstString &path) override; bool GetRemoteOSVersion () override; @@ -101,6 +102,9 @@ public: lldb_private::ArchSpec GetRemoteSystemArchitecture () override; + size_t + GetEnvironment (lldb_private::StringList &environment) override; + bool IsConnected () const override; @@ -110,40 +114,48 @@ public: int *status_ptr, // Pass NULL if you don't want the process exit status int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit std::string *command_output, // Pass NULL if you don't want the command output - uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish + uint32_t timeout_sec) override;// Timeout in seconds to wait for shell program to finish virtual lldb_private::Error - MakeDirectory (const char *path, uint32_t mode); + MakeDirectory (const char *path, uint32_t mode) override; virtual lldb_private::Error - GetFilePermissions (const char *path, uint32_t &file_permissions); + GetFilePermissions (const char *path, uint32_t &file_permissions) override; virtual lldb_private::Error - SetFilePermissions (const char *path, uint32_t file_permissions); + SetFilePermissions (const char *path, uint32_t file_permissions) override; virtual bool - GetFileExists (const lldb_private::FileSpec& file_spec); + GetFileExists (const lldb_private::FileSpec& file_spec) override; virtual lldb_private::Error - Unlink (const char *path); + Unlink (const char *path) override; + + lldb_private::Error + LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info) override; + + lldb::ProcessSP + Attach (lldb_private::ProcessAttachInfo &attach_info, + lldb_private::Debugger &debugger, + lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one + lldb_private::Error &error) override; lldb::ProcessSP DebugProcess (lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Debugger &debugger, lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one - lldb_private::Listener &listener, lldb_private::Error &error) override; virtual std::string - GetPlatformSpecificConnectionInformation(); + GetPlatformSpecificConnectionInformation() override; virtual bool CalculateMD5 (const lldb_private::FileSpec& file_spec, uint64_t &low, - uint64_t &high); + uint64_t &high) override; virtual void - CalculateTrapHandlerSymbolNames (); + CalculateTrapHandlerSymbolNames () override; lldb_private::Error ConnectRemote (lldb_private::Args& args) override; diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 05fbc5101278..43eae4d906ec 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -16,14 +16,15 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" +#include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamString.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" #include "lldb/Target/Process.h" @@ -56,7 +57,7 @@ PlatformRemoteGDBServer::Terminate () } } -Platform* +PlatformSP PlatformRemoteGDBServer::CreateInstance (bool force, const lldb_private::ArchSpec *arch) { bool create = force; @@ -65,8 +66,8 @@ PlatformRemoteGDBServer::CreateInstance (bool force, const lldb_private::ArchSpe create = !arch->TripleVendorWasSpecified() && !arch->TripleOSWasSpecified(); } if (create) - return new PlatformRemoteGDBServer (); - return NULL; + return PlatformSP(new PlatformRemoteGDBServer()); + return PlatformSP(); } @@ -100,14 +101,13 @@ PlatformRemoteGDBServer::GetDescription () } Error -PlatformRemoteGDBServer::ResolveExecutable (const FileSpec &exe_file, - const ArchSpec &exe_arch, +PlatformRemoteGDBServer::ResolveExecutable (const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, const FileSpecList *module_search_paths_ptr) { Error error; //error.SetErrorString ("PlatformRemoteGDBServer::ResolveExecutable() is unimplemented"); - if (m_gdb_client.GetFileExists(exe_file)) + if (m_gdb_client.GetFileExists(module_spec.GetFileSpec())) return error; // TODO: get the remote end to somehow resolve this file error.SetErrorString("file not found on remote end"); @@ -421,7 +421,6 @@ lldb::ProcessSP PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Debugger &debugger, lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one - lldb_private::Listener &listener, lldb_private::Error &error) { lldb::ProcessSP process_sp; @@ -473,7 +472,7 @@ PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_i // The darwin always currently uses the GDB remote debugger plug-in // so even when debugging locally we are debugging remotely! - process_sp = target->CreateProcess (listener, "gdb-remote", NULL); + process_sp = target->CreateProcess (launch_info.GetListenerForProcess(debugger), "gdb-remote", NULL); if (process_sp) { @@ -488,10 +487,16 @@ PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_i port + port_offset); assert (connect_url_len < (int)sizeof(connect_url)); error = process_sp->ConnectRemote (NULL, connect_url); + // Retry the connect remote one time... + if (error.Fail()) + error = process_sp->ConnectRemote (NULL, connect_url); if (error.Success()) error = process_sp->Launch(launch_info); else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) + { + printf ("error: connect remote failed (%s)\n", error.AsCString()); m_gdb_client.KillSpawnedProcess(debugserver_pid); + } } } } @@ -509,7 +514,6 @@ lldb::ProcessSP PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info, Debugger &debugger, Target *target, // Can be NULL, if NULL create a new target, else use existing one - Listener &listener, Error &error) { lldb::ProcessSP process_sp; @@ -561,7 +565,7 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info, // The darwin always currently uses the GDB remote debugger plug-in // so even when debugging locally we are debugging remotely! - process_sp = target->CreateProcess (listener, "gdb-remote", NULL); + process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL); if (process_sp) { diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index e236e97c8bb3..90b16b8b8fa9 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -29,7 +29,7 @@ public: static void Terminate (); - static lldb_private::Platform* + static lldb::PlatformSP CreateInstance (bool force, const lldb_private::ArchSpec *arch); static lldb_private::ConstString @@ -64,8 +64,7 @@ public: // lldb_private::Platform functions //------------------------------------------------------------ virtual lldb_private::Error - ResolveExecutable (const lldb_private::FileSpec &exe_file, - const lldb_private::ArchSpec &arch, + ResolveExecutable (const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, const lldb_private::FileSpecList *module_search_paths_ptr); @@ -92,14 +91,12 @@ public: DebugProcess (lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Debugger &debugger, lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one - lldb_private::Listener &listener, lldb_private::Error &error); virtual lldb::ProcessSP Attach (lldb_private::ProcessAttachInfo &attach_info, lldb_private::Debugger &debugger, lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one - lldb_private::Listener &listener, lldb_private::Error &error); virtual bool diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp index 4b488444de1e..5a0b5ed14194 100644 --- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp @@ -258,8 +258,7 @@ ProcessFreeBSD::SendMessage(const ProcessMessage &message) case ProcessMessage::eLimboMessage: case ProcessMessage::eExitMessage: - m_exit_status = message.GetExitStatus(); - SetExitStatus(m_exit_status, NULL); + SetExitStatus(message.GetExitStatus(), NULL); break; case ProcessMessage::eSignalMessage: diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index 63439b155111..84e35ba22644 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -25,6 +25,7 @@ #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" #include "lldb/Host/Host.h" +#include "lldb/Host/ThreadLauncher.h" #include "lldb/Target/Thread.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Utility/PseudoTerminal.h" @@ -112,6 +113,7 @@ PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, log->Printf("PT_GETREGS: ax=0x%lx", r->r_rax); } #endif +#ifndef __powerpc__ if (req == PT_GETDBREGS || req == PT_SETDBREGS) { struct dbreg *r = (struct dbreg *) addr; char setget = (req == PT_GETDBREGS) ? 'G' : 'S'; @@ -119,6 +121,7 @@ PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, for (int i = 0; i <= 7; i++) log->Printf("PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]); } +#endif } return result; @@ -309,9 +312,14 @@ ReadRegOperation::Execute(ProcessMonitor *monitor) if ((rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)®s, 0)) < 0) { m_result = false; } else { - if (m_size == sizeof(uintptr_t)) - m_value = *(uintptr_t *)(((caddr_t)®s) + m_offset); - 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)®s) + m_offset); + else if (m_size == sizeof(uint64_t)) + m_value = *(uint64_t *)(((caddr_t)®s) + m_offset); + else memcpy(&m_value, (((caddr_t)®s) + m_offset), m_size); m_result = true; } @@ -810,8 +818,6 @@ ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, const lldb_private::ProcessLaunchInfo & /* launch_info */, lldb_private::Error &error) : m_process(static_cast(process)), - m_operation_thread(LLDB_INVALID_HOST_THREAD), - m_monitor_thread(LLDB_INVALID_HOST_THREAD), m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), m_operation(0) @@ -852,7 +858,7 @@ WAIT_AGAIN: // Finally, start monitoring the child process for change in state. m_monitor_thread = Host::StartMonitoringChildProcess( ProcessMonitor::MonitorCallback, this, GetPID(), true); - if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread)) + if (!m_monitor_thread.IsJoinable()) { error.SetErrorToGenericError(); error.SetErrorString("Process launch failed."); @@ -864,8 +870,6 @@ ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, lldb::pid_t pid, lldb_private::Error &error) : m_process(static_cast(process)), - m_operation_thread(LLDB_INVALID_HOST_THREAD), - m_monitor_thread(LLDB_INVALID_HOST_THREAD), m_pid(pid), m_terminal_fd(-1), m_operation(0) @@ -904,7 +908,7 @@ WAIT_AGAIN: // Finally, start monitoring the child process for change in state. m_monitor_thread = Host::StartMonitoringChildProcess( ProcessMonitor::MonitorCallback, this, GetPID(), true); - if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread)) + if (!m_monitor_thread.IsJoinable()) { error.SetErrorToGenericError(); error.SetErrorString("Process attach failed."); @@ -924,11 +928,10 @@ ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Error &error) { static const char *g_thread_name = "lldb.process.freebsd.operation"; - if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread)) + if (m_operation_thread.IsJoinable()) return; - m_operation_thread = - Host::ThreadCreate(g_thread_name, LaunchOpThread, args, &error); + m_operation_thread = ThreadLauncher::LaunchThread(g_thread_name, LaunchOpThread, args, &error); } void * @@ -1101,11 +1104,10 @@ ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error { static const char *g_thread_name = "lldb.process.freebsd.operation"; - if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread)) + if (m_operation_thread.IsJoinable()) return; - m_operation_thread = - Host::ThreadCreate(g_thread_name, AttachOpThread, args, &error); + m_operation_thread = ThreadLauncher::LaunchThread(g_thread_name, AttachOpThread, args, &error); } void * @@ -1113,14 +1115,13 @@ ProcessMonitor::AttachOpThread(void *arg) { AttachArgs *args = static_cast(arg); - if (!Attach(args)) - return NULL; + Attach(args); ServeOperation(args); return NULL; } -bool +void ProcessMonitor::Attach(AttachArgs *args) { lldb::pid_t pid = args->m_pid; @@ -1132,27 +1133,24 @@ ProcessMonitor::Attach(AttachArgs *args) { args->m_error.SetErrorToGenericError(); args->m_error.SetErrorString("Attaching to process 1 is not allowed."); - goto FINISH; + return; } // Attach to the requested process. if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0) { args->m_error.SetErrorToErrno(); - goto FINISH; + return; } int status; if ((status = waitpid(pid, NULL, 0)) < 0) { args->m_error.SetErrorToErrno(); - goto FINISH; + return; } process.SendMessage(ProcessMessage::Attach(pid)); - -FINISH: - return args->m_error.Success(); } size_t @@ -1714,13 +1712,11 @@ ProcessMonitor::DupDescriptor(const char *path, int fd, int flags) void ProcessMonitor::StopMonitoringChildProcess() { - lldb::thread_result_t thread_result; - - if (IS_VALID_LLDB_HOST_THREAD(m_monitor_thread)) + if (m_monitor_thread.IsJoinable()) { - Host::ThreadCancel(m_monitor_thread, NULL); - Host::ThreadJoin(m_monitor_thread, &thread_result, NULL); - m_monitor_thread = LLDB_INVALID_HOST_THREAD; + m_monitor_thread.Cancel(); + m_monitor_thread.Join(nullptr); + m_monitor_thread.Reset(); } } @@ -1764,12 +1760,10 @@ ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid) void ProcessMonitor::StopOpThread() { - lldb::thread_result_t result; - - if (!IS_VALID_LLDB_HOST_THREAD(m_operation_thread)) + if (!m_operation_thread.IsJoinable()) return; - Host::ThreadCancel(m_operation_thread, NULL); - Host::ThreadJoin(m_operation_thread, &result, NULL); - m_operation_thread = LLDB_INVALID_HOST_THREAD; + m_operation_thread.Cancel(); + m_operation_thread.Join(nullptr); + m_operation_thread.Reset(); } diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h index 314743b00754..935fd85ed37a 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h @@ -17,6 +17,7 @@ // C++ Includes // Other libraries and framework includes #include "lldb/lldb-types.h" +#include "lldb/Host/HostThread.h" #include "lldb/Host/Mutex.h" namespace lldb_private @@ -212,8 +213,8 @@ public: private: ProcessFreeBSD *m_process; - lldb::thread_t m_operation_thread; - lldb::thread_t m_monitor_thread; + lldb_private::HostThread m_operation_thread; + lldb_private::HostThread m_monitor_thread; lldb::pid_t m_pid; int m_terminal_fd; @@ -289,7 +290,7 @@ private: static void * AttachOpThread(void *args); - static bool + static void Attach(AttachArgs *args); static void diff --git a/source/Plugins/Process/POSIX/POSIXThread.cpp b/source/Plugins/Process/POSIX/POSIXThread.cpp index d48f8f9dd307..1057585e1b2a 100644 --- a/source/Plugins/Process/POSIX/POSIXThread.cpp +++ b/source/Plugins/Process/POSIX/POSIXThread.cpp @@ -20,27 +20,30 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" +#include "lldb/Host/HostNativeThread.h" #include "lldb/Host/HostInfo.h" #include "lldb/Target/Process.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadSpec.h" +#include "llvm/ADT/SmallString.h" #include "POSIXStopInfo.h" #include "POSIXThread.h" #include "ProcessPOSIX.h" #include "ProcessPOSIXLog.h" -#include "ProcessMonitor.h" +#include "Plugins/Process/Linux/ProcessMonitor.h" #include "RegisterContextPOSIXProcessMonitor_arm64.h" #include "RegisterContextPOSIXProcessMonitor_mips64.h" +#include "RegisterContextPOSIXProcessMonitor_powerpc.h" #include "RegisterContextPOSIXProcessMonitor_x86.h" -#include "RegisterContextLinux_arm64.h" -#include "RegisterContextLinux_i386.h" -#include "RegisterContextLinux_x86_64.h" -#include "RegisterContextFreeBSD_i386.h" -#include "RegisterContextFreeBSD_mips64.h" -#include "RegisterContextFreeBSD_x86_64.h" - -#include "UnwindLLDB.h" +#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h" +#include "Plugins/Process/Utility/RegisterContextLinux_i386.h" +#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.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/UnwindLLDB.h" using namespace lldb; using namespace lldb_private; @@ -140,7 +143,9 @@ POSIXThread::GetName () { if (!m_thread_name_valid) { - SetName(Host::GetThreadName(GetProcess()->GetID(), GetID()).c_str()); + llvm::SmallString<32> thread_name; + HostNativeThread::GetName(GetID(), thread_name); + m_thread_name = thread_name.c_str(); m_thread_name_valid = true; } @@ -164,6 +169,14 @@ POSIXThread::GetRegisterContext() case llvm::Triple::FreeBSD: switch (target_arch.GetMachine()) { + 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; @@ -226,6 +239,14 @@ POSIXThread::GetRegisterContext() 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: { @@ -621,6 +642,8 @@ POSIXThread::GetRegisterIndexFromOffset(unsigned offset) case llvm::Triple::aarch64: case llvm::Triple::mips64: + case llvm::Triple::ppc: + case llvm::Triple::ppc64: case llvm::Triple::x86: case llvm::Triple::x86_64: { @@ -652,6 +675,8 @@ POSIXThread::GetRegisterName(unsigned reg) case llvm::Triple::aarch64: 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); diff --git a/source/Plugins/Process/POSIX/POSIXThread.h b/source/Plugins/Process/POSIX/POSIXThread.h index 51d6645f209d..56dcccbfb0f9 100644 --- a/source/Plugins/Process/POSIX/POSIXThread.h +++ b/source/Plugins/Process/POSIX/POSIXThread.h @@ -17,7 +17,7 @@ // Other libraries and framework includes #include "lldb/Target/Thread.h" -#include "RegisterContextPOSIX.h" +#include "Plugins/Process/Utility/RegisterContextPOSIX.h" class ProcessMessage; class ProcessMonitor; diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp index f340631c7d07..0e5ab5a8d8b1 100644 --- a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp +++ b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp @@ -16,6 +16,7 @@ // Other libraries and framework includes #include "lldb/Breakpoint/Watchpoint.h" #include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Host/FileSpec.h" @@ -28,7 +29,7 @@ #include "ProcessPOSIX.h" #include "ProcessPOSIXLog.h" #include "Plugins/Process/Utility/InferiorCallPOSIX.h" -#include "ProcessMonitor.h" +#include "Plugins/Process/Linux/ProcessMonitor.h" #include "POSIXThread.h" using namespace lldb; @@ -140,8 +141,8 @@ ProcessPOSIX::DoAttachToProcessWithID(lldb::pid_t pid) // Resolve the executable module ModuleSP exe_module_sp; FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); - error = platform_sp->ResolveExecutable(process_info.GetExecutableFile(), - m_target.GetArchitecture(), + ModuleSpec exe_module_spec(process_info.GetExecutableFile(), m_target.GetArchitecture()); + error = platform_sp->ResolveExecutable(exe_module_spec, exe_module_sp, executable_search_paths.GetSize() ? &executable_search_paths : NULL); if (!error.Success()) @@ -176,9 +177,9 @@ ProcessPOSIX::WillLaunch(Module* module) } const char * -ProcessPOSIX::GetFilePath(const lldb_private::FileAction *file_action, const char *default_path) +ProcessPOSIX::GetFilePath(const lldb_private::FileAction *file_action, const char *default_path, + const char *dbg_pts_path) { - const char *pts_name = "/dev/pts/"; const char *path = NULL; if (file_action) @@ -190,11 +191,11 @@ ProcessPOSIX::GetFilePath(const lldb_private::FileAction *file_action, const cha // (/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 (!path || ::strncmp(path, pts_name, ::strlen(pts_name)) == 0) + if (!path || (dbg_pts_path && + ::strncmp(path, dbg_pts_path, ::strlen(dbg_pts_path)) == 0)) path = default_path; } } - return path; } @@ -224,14 +225,16 @@ ProcessPOSIX::DoLaunch (Module *module, const char *stdout_path = NULL; const char *stderr_path = NULL; + const char * dbg_pts_path = launch_info.GetPTY().GetSlaveName(NULL,0); + file_action = launch_info.GetFileActionForFD (STDIN_FILENO); - stdin_path = GetFilePath(file_action, stdin_path); + stdin_path = GetFilePath(file_action, stdin_path, dbg_pts_path); file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); - stdout_path = GetFilePath(file_action, stdout_path); + stdout_path = GetFilePath(file_action, stdout_path, dbg_pts_path); file_action = launch_info.GetFileActionForFD (STDERR_FILENO); - stderr_path = GetFilePath(file_action, stderr_path); + stderr_path = GetFilePath(file_action, stderr_path, dbg_pts_path); m_monitor = new ProcessMonitor (this, module, @@ -338,6 +341,11 @@ ProcessPOSIX::DoDestroy() { 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(); @@ -363,11 +371,11 @@ ProcessPOSIX::DoDidExec() 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()); - Error error = platform_sp->ResolveExecutable(process_info.GetExecutableFile(), - target->GetArchitecture(), - exe_module_sp, - executable_search_paths.GetSize() ? &executable_search_paths : NULL); + Error 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, true); @@ -432,8 +440,7 @@ ProcessPOSIX::SendMessage(const ProcessMessage &message) // FIXME: I'm not sure we need to do this. if (message.GetTID() == GetID()) { - m_exit_status = message.GetExitStatus(); - SetExitStatus(m_exit_status, NULL); + SetExitStatus(message.GetExitStatus(), NULL); } else if (!IsAThreadRunning()) SetPrivateState(eStateStopped); diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.h b/source/Plugins/Process/POSIX/ProcessPOSIX.h index 033accf17f29..f152356b3093 100644 --- a/source/Plugins/Process/POSIX/ProcessPOSIX.h +++ b/source/Plugins/Process/POSIX/ProcessPOSIX.h @@ -42,104 +42,104 @@ public: // Process protocol. //------------------------------------------------------------------ virtual void - Finalize(); + Finalize() override; virtual bool - CanDebug(lldb_private::Target &target, bool plugin_specified_by_name); + CanDebug(lldb_private::Target &target, bool plugin_specified_by_name) override; virtual lldb_private::Error - WillLaunch(lldb_private::Module *module); + WillLaunch(lldb_private::Module *module) override; virtual lldb_private::Error - DoAttachToProcessWithID(lldb::pid_t pid); + DoAttachToProcessWithID(lldb::pid_t pid) override; virtual lldb_private::Error - DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info); + DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override; virtual lldb_private::Error DoLaunch (lldb_private::Module *exe_module, - lldb_private::ProcessLaunchInfo &launch_info); + lldb_private::ProcessLaunchInfo &launch_info) override; virtual void - DidLaunch(); + DidLaunch() override; virtual lldb_private::Error - DoResume(); + DoResume() override; virtual lldb_private::Error - DoHalt(bool &caused_stop); + DoHalt(bool &caused_stop) override; virtual lldb_private::Error - DoDetach(bool keep_stopped) = 0; + DoDetach(bool keep_stopped) override = 0; virtual lldb_private::Error - DoSignal(int signal); + DoSignal(int signal) override; virtual lldb_private::Error - DoDestroy(); + DoDestroy() override; virtual void - DoDidExec(); + DoDidExec() override; virtual void - RefreshStateAfterStop(); + RefreshStateAfterStop() override; virtual bool - IsAlive(); + IsAlive() override; virtual size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, - lldb_private::Error &error); + lldb_private::Error &error) override; virtual size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, - lldb_private::Error &error); + lldb_private::Error &error) override; virtual lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions, - lldb_private::Error &error); + lldb_private::Error &error) override; virtual lldb_private::Error - DoDeallocateMemory(lldb::addr_t ptr); + DoDeallocateMemory(lldb::addr_t ptr) override; virtual size_t GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); virtual lldb_private::Error - EnableBreakpointSite(lldb_private::BreakpointSite *bp_site); + EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; virtual lldb_private::Error - DisableBreakpointSite(lldb_private::BreakpointSite *bp_site); + DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; virtual lldb_private::Error - EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true); + EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override; virtual lldb_private::Error - DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true); + DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override; virtual lldb_private::Error - GetWatchpointSupportInfo(uint32_t &num); + GetWatchpointSupportInfo(uint32_t &num) override; virtual lldb_private::Error - GetWatchpointSupportInfo(uint32_t &num, bool &after); + GetWatchpointSupportInfo(uint32_t &num, bool &after) override; virtual uint32_t UpdateThreadListIfNeeded(); virtual bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list) = 0; + lldb_private::ThreadList &new_thread_list) override = 0; virtual lldb::ByteOrder GetByteOrder() const; virtual lldb::addr_t - GetImageInfoAddress(); + GetImageInfoAddress() override; virtual size_t - PutSTDIN(const char *buf, size_t len, lldb_private::Error &error); + PutSTDIN(const char *buf, size_t len, lldb_private::Error &error) override; const lldb::DataBufferSP GetAuxvData () override; @@ -154,7 +154,8 @@ public: ProcessMonitor & GetMonitor() { assert(m_monitor); return *m_monitor; } - const char *GetFilePath(const lldb_private::FileAction *file_action, const char *default_path); + const char *GetFilePath(const lldb_private::FileAction *file_action, const char *default_path, + const char *dbg_pts_path); /// Stops all threads in the process. /// The \p stop_tid parameter indicates the thread which initiated the stop. diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp index 9109cdb000ae..ec34d9e28161 100644 --- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp @@ -10,10 +10,10 @@ #include "lldb/Target/Thread.h" #include "lldb/Core/RegisterValue.h" -#include "RegisterContextPOSIX_arm64.h" +#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" #include "ProcessPOSIX.h" #include "RegisterContextPOSIXProcessMonitor_arm64.h" -#include "ProcessMonitor.h" +#include "Plugins/Process/Linux/ProcessMonitor.h" #define REG_CONTEXT_SIZE (GetGPRSize()) diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp index 9bfe236de139..6717d20da056 100644 --- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp @@ -10,10 +10,10 @@ #include "lldb/Target/Thread.h" #include "lldb/Core/RegisterValue.h" -#include "RegisterContextPOSIX_mips64.h" +#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h" #include "ProcessPOSIX.h" #include "RegisterContextPOSIXProcessMonitor_mips64.h" -#include "ProcessMonitor.h" +#include "Plugins/Process/Linux/ProcessMonitor.h" using namespace lldb_private; using namespace lldb; diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp new file mode 100644 index 000000000000..b542db4779db --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp @@ -0,0 +1,321 @@ +//===-- RegisterContextPOSIXProcessMonitor_powerpc.h ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#include "lldb/Target/Thread.h" +#include "lldb/Core/RegisterValue.h" + +#include "RegisterContextPOSIX_powerpc.h" +#include "ProcessPOSIX.h" +#include "RegisterContextPOSIXProcessMonitor_powerpc.h" +#include "ProcessMonitor.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(); + ProcessPOSIX *process = static_cast(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() +{ + // XXX not yet implemented + return false; +} + +bool +RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR() +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize()); +} + +bool +RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR() +{ + // XXX not yet implemented + 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)) + { + Error 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; + } + 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_powerpc::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_powerpc::ReadAllRegisterValues(DataBufferSP &data_sp) +{ + bool success = false; + data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); + if (data_sp && 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(); + } + } + } + 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/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h new file mode 100644 index 000000000000..92a331285515 --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h @@ -0,0 +1,95 @@ +//===-- RegisterContextPOSIXProcessMonitor_powerpc.h -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_ +#define liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_ + +#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.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 + ReadGPR(); + + bool + ReadFPR(); + + bool + WriteGPR(); + + bool + WriteFPR(); + + // 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); + + bool + WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); + + bool + ReadAllRegisterValues(lldb::DataBufferSP &data_sp); + + bool + WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); + + uint32_t + SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write); + + bool + ClearHardwareWatchpoint(uint32_t hw_index); + + bool + HardwareSingleStep(bool enable); + + // POSIXBreakpointProtocol + bool + UpdateAfterBreakpoint(); + + unsigned + GetRegisterIndexFromOffset(unsigned offset); + + bool + IsWatchpointHit(uint32_t hw_index); + + bool + ClearWatchpointHits(); + + lldb::addr_t + GetWatchpointAddress(uint32_t hw_index); + + bool + IsWatchpointVacant(uint32_t hw_index); + + bool + SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index); + + uint32_t + NumSupportedHardwareWatchpoints(); + +private: + ProcessMonitor & + GetMonitor(); +}; + +#endif diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp index e534f3b4f9d0..1956e4584fa9 100644 --- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp @@ -10,9 +10,13 @@ #include "lldb/Target/Thread.h" #include "lldb/Core/RegisterValue.h" -#include "ProcessPOSIX.h" +#include "Plugins/Process/POSIX/ProcessPOSIX.h" #include "RegisterContextPOSIXProcessMonitor_x86.h" -#include "ProcessMonitor.h" +#if defined(__FreeBSD__) +#include "Plugins/Process/FreeBSD/ProcessMonitor.h" +#else +#include "Plugins/Process/Linux/ProcessMonitor.h" +#endif using namespace lldb_private; using namespace lldb; @@ -48,6 +52,7 @@ size_and_rw_bits(size_t size, bool read, bool write) 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. } } diff --git a/source/Plugins/Process/Utility/ARMDefines.h b/source/Plugins/Process/Utility/ARMDefines.h index 2c8ad3586af1..cfb33beb447a 100644 --- a/source/Plugins/Process/Utility/ARMDefines.h +++ b/source/Plugins/Process/Utility/ARMDefines.h @@ -45,7 +45,8 @@ typedef enum #define COND_AL 0xE // Always (unconditional) Always (unconditional) Any #define COND_UNCOND 0xF -static inline const char *ARMCondCodeToString(uint32_t CC) +static inline const char * +ARMCondCodeToString(uint32_t CC) { switch (CC) { default: assert(0 && "Unknown condition code"); @@ -67,6 +68,37 @@ static inline const char *ARMCondCodeToString(uint32_t CC) } } +static inline bool +ARMConditionPassed(const uint32_t condition, const uint32_t cpsr) +{ + const uint32_t cpsr_n = (cpsr >> 31) & 1u; // Negative condition code flag + const uint32_t cpsr_z = (cpsr >> 30) & 1u; // Zero condition code flag + const uint32_t cpsr_c = (cpsr >> 29) & 1u; // Carry condition code flag + const uint32_t cpsr_v = (cpsr >> 28) & 1u; // Overflow condition code flag + + switch (condition) { + case COND_EQ: return (cpsr_z == 1); + case COND_NE: return (cpsr_z == 0); + case COND_CS: return (cpsr_c == 1); + case COND_CC: return (cpsr_c == 0); + case COND_MI: return (cpsr_n == 1); + case COND_PL: return (cpsr_n == 0); + case COND_VS: return (cpsr_v == 1); + case COND_VC: return (cpsr_v == 0); + case COND_HI: return ((cpsr_c == 1) && (cpsr_z == 0)); + case COND_LS: return ((cpsr_c == 0) || (cpsr_z == 1)); + case COND_GE: return (cpsr_n == cpsr_v); + case COND_LT: return (cpsr_n != cpsr_v); + case COND_GT: return ((cpsr_z == 0) && (cpsr_n == cpsr_v)); + case COND_LE: return ((cpsr_z == 1) || (cpsr_n != cpsr_v)); + case COND_AL: + case COND_UNCOND: + default: + return true; + } + return false; +} + // Bit positions for CPSR #define CPSR_T_POS 5 #define CPSR_F_POS 6 diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index 3507ccf92065..1088924bfeac 100644 --- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -81,6 +81,7 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict else { Clear(); + printf("error: register sets must have valid names\n"); return 0; } } @@ -121,6 +122,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict if (reg_info.name == NULL) { Clear(); + printf("error: registers must have valid names\n"); + reg_info_dict.Dump(); return 0; } @@ -290,6 +293,7 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict if (!success) { Clear(); + reg_info_dict.Dump(); return 0; } } @@ -297,6 +301,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict if (bitsize == 0) { Clear(); + printf("error: invalid or missing 'bitsize' key/value pair in register dictionary\n"); + reg_info_dict.Dump(); return 0; } @@ -308,6 +314,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict if (Args::StringToFormat(format_cstr, reg_info.format, NULL).Fail()) { Clear(); + printf("error: invalid 'format' value in register dictionary\n"); + reg_info_dict.Dump(); return 0; } } @@ -326,6 +334,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict if (static_cast(set) >= m_sets.size()) { Clear(); + printf("error: invalid 'set' value in register dictionary, valid values are 0 - %i\n", (int)set); + reg_info_dict.Dump(); return 0; } @@ -409,6 +419,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict else { Clear(); + printf("error: items in the 'registers' array must be dictionaries\n"); + regs.Dump(); return 0; } } diff --git a/source/Plugins/Process/Utility/HistoryThread.cpp b/source/Plugins/Process/Utility/HistoryThread.cpp index 590bb0162c8a..206b8290c5fd 100644 --- a/source/Plugins/Process/Utility/HistoryThread.cpp +++ b/source/Plugins/Process/Utility/HistoryThread.cpp @@ -39,7 +39,7 @@ HistoryThread::HistoryThread (lldb_private::Process &process, m_originating_unique_thread_id (tid), m_queue_id (LLDB_INVALID_QUEUE_ID) { - m_unwinder_ap.reset (new HistoryUnwind (*this, pcs, stop_id, stop_id_is_valid)); + m_unwinder_ap.reset (new HistoryUnwind (*this, pcs, stop_id_is_valid)); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); if (log) log->Printf ("%p HistoryThread::HistoryThread", diff --git a/source/Plugins/Process/Utility/HistoryThread.h b/source/Plugins/Process/Utility/HistoryThread.h index f9a431d8340b..51173c626d71 100644 --- a/source/Plugins/Process/Utility/HistoryThread.h +++ b/source/Plugins/Process/Utility/HistoryThread.h @@ -101,6 +101,18 @@ public: { m_thread_name = name; } + + virtual const char * + GetName () + { + return m_thread_name.c_str(); + } + + virtual void + SetName(const char *name) + { + m_thread_name = name; + } protected: virtual lldb::StackFrameListSP diff --git a/source/Plugins/Process/Utility/HistoryUnwind.cpp b/source/Plugins/Process/Utility/HistoryUnwind.cpp index f809ebedcfc8..14afcbee0b49 100644 --- a/source/Plugins/Process/Utility/HistoryUnwind.cpp +++ b/source/Plugins/Process/Utility/HistoryUnwind.cpp @@ -24,11 +24,9 @@ using namespace lldb_private; HistoryUnwind::HistoryUnwind (Thread &thread, std::vector pcs, - uint32_t stop_id, bool stop_id_is_valid) : Unwind (thread), m_pcs (pcs), - m_stop_id (stop_id), m_stop_id_is_valid (stop_id_is_valid) { } diff --git a/source/Plugins/Process/Utility/HistoryUnwind.h b/source/Plugins/Process/Utility/HistoryUnwind.h index 0661b8028608..733f93e1ff87 100644 --- a/source/Plugins/Process/Utility/HistoryUnwind.h +++ b/source/Plugins/Process/Utility/HistoryUnwind.h @@ -21,7 +21,7 @@ namespace lldb_private { class HistoryUnwind : public lldb_private::Unwind { public: - HistoryUnwind (Thread &thread, std::vector pcs, uint32_t stop_id, bool stop_id_is_valid); + HistoryUnwind (Thread &thread, std::vector pcs, bool stop_id_is_valid); virtual ~HistoryUnwind (); @@ -42,7 +42,6 @@ protected: private: std::vector m_pcs; - uint32_t m_stop_id; bool m_stop_id_is_valid; }; diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index 4a94457466be..7db83ae5467f 100644 --- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -98,13 +98,11 @@ lldb_private::InferiorCallMmap (Process *process, ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset }; - ThreadPlanCallFunction *call_function_thread_plan - = new ThreadPlanCallFunction (*thread, - mmap_range.GetBaseAddress(), - clang_void_ptr_type, - args, - options); - lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan); + lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, + mmap_range.GetBaseAddress(), + clang_void_ptr_type, + args, + options)); if (call_plan_sp) { StreamFile error_strm; @@ -241,13 +239,11 @@ lldb_private::InferiorCall (Process *process, ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - ThreadPlanCallFunction *call_function_thread_plan - = new ThreadPlanCallFunction (*thread, - *address, - clang_void_ptr_type, - llvm::ArrayRef(), - options); - lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan); + lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, + *address, + clang_void_ptr_type, + llvm::ArrayRef(), + options)); if (call_plan_sp) { StreamString error_strm; diff --git a/source/Plugins/Process/Utility/InstructionUtils.h b/source/Plugins/Process/Utility/InstructionUtils.h index 813990095c49..6226fbc04b08 100644 --- a/source/Plugins/Process/Utility/InstructionUtils.h +++ b/source/Plugins/Process/Utility/InstructionUtils.h @@ -20,7 +20,7 @@ static inline uint64_t Bits64 (const uint64_t bits, const uint32_t msbit, const uint32_t lsbit) { assert(msbit < 64 && lsbit <= msbit); - return (bits >> lsbit) & ((1u << (msbit - lsbit + 1)) - 1); + return (bits >> lsbit) & ((1ull << (msbit - lsbit + 1)) - 1); } // Return the bit field(s) from the most significant bit (msbit) to the diff --git a/source/Plugins/Process/Utility/LinuxSignals.cpp b/source/Plugins/Process/Utility/LinuxSignals.cpp index fb49df681cae..11a3eef23529 100644 --- a/source/Plugins/Process/Utility/LinuxSignals.cpp +++ b/source/Plugins/Process/Utility/LinuxSignals.cpp @@ -53,7 +53,7 @@ LinuxSignals::Reset() AddSignal (24, "SIGXCPU", "XCPU", false, true , true , "CPU resource exceeded"); AddSignal (25, "SIGXFSZ", "XFSZ", false, true , true , "file size limit exceeded"); AddSignal (26, "SIGVTALRM", "VTALRM", false, true , true , "virtual time alarm"); - AddSignal (27, "SIGPROF", "PROF", false, true , true , "profiling time alarm"); + AddSignal (27, "SIGPROF", "PROF", false, false, false, "profiling time alarm"); AddSignal (28, "SIGWINCH", "WINCH", false, true , true , "window size changes"); AddSignal (29, "SIGPOLL", "POLL", false, true , true , "pollable event"); AddSignal (29, "SIGIO", "IO", false, true , true , "input/output ready"); diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp new file mode 100644 index 000000000000..5170e6d2accb --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp @@ -0,0 +1,230 @@ +//===-- RegisterContextFreeBSD_powerpc.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#include +#include "RegisterContextPOSIX_powerpc.h" +#include "RegisterContextFreeBSD_powerpc.h" + +using namespace lldb_private; +using namespace lldb; + +// http://svnweb.freebsd.org/base/head/sys/powerpc/include/reg.h +typedef struct _GPR64 +{ + uint64_t r0; + uint64_t r1; + uint64_t r2; + uint64_t r3; + uint64_t r4; + uint64_t r5; + uint64_t r6; + uint64_t r7; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t r16; + uint64_t r17; + uint64_t r18; + uint64_t r19; + uint64_t r20; + uint64_t r21; + uint64_t r22; + uint64_t r23; + uint64_t r24; + uint64_t r25; + uint64_t r26; + uint64_t r27; + uint64_t r28; + uint64_t r29; + uint64_t r30; + uint64_t r31; + uint64_t lr; + uint64_t cr; + uint64_t xer; + uint64_t ctr; + uint64_t pc; +} GPR64; + +typedef struct _GPR32 +{ + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t r12; + uint32_t r13; + uint32_t r14; + uint32_t r15; + uint32_t r16; + uint32_t r17; + uint32_t r18; + uint32_t r19; + uint32_t r20; + uint32_t r21; + uint32_t r22; + uint32_t r23; + uint32_t r24; + uint32_t r25; + uint32_t r26; + uint32_t r27; + uint32_t r28; + uint32_t r29; + uint32_t r30; + uint32_t r31; + uint32_t lr; + uint32_t cr; + uint32_t xer; + uint32_t ctr; + uint32_t pc; +} GPR32; + +typedef struct _FPR +{ + uint64_t f0; + uint64_t f1; + uint64_t f2; + uint64_t f3; + uint64_t f4; + uint64_t f5; + uint64_t f6; + uint64_t f7; + uint64_t f8; + uint64_t f9; + uint64_t f10; + uint64_t f11; + uint64_t f12; + uint64_t f13; + uint64_t f14; + uint64_t f15; + uint64_t f16; + uint64_t f17; + uint64_t f18; + uint64_t f19; + uint64_t f20; + uint64_t f21; + uint64_t f22; + uint64_t f23; + uint64_t f24; + uint64_t f25; + uint64_t f26; + uint64_t f27; + uint64_t f28; + uint64_t f29; + uint64_t f30; + uint64_t f31; + uint64_t fpscr; +} FPR; + +//--------------------------------------------------------------------------- +// Include RegisterInfos_powerpc to declare our g_register_infos_powerpc structure. +//--------------------------------------------------------------------------- +#define DECLARE_REGISTER_INFOS_POWERPC_STRUCT +#include "RegisterInfos_powerpc.h" +#undef DECLARE_REGISTER_INFOS_POWERPC_STRUCT + +RegisterContextFreeBSD_powerpc::RegisterContextFreeBSD_powerpc(const ArchSpec &target_arch) : + RegisterInfoInterface(target_arch) +{ +} + +RegisterContextFreeBSD_powerpc::~RegisterContextFreeBSD_powerpc() +{ +} + +size_t +RegisterContextFreeBSD_powerpc::GetGPRSize() const +{ + // This is an 'abstract' base, so no GPR struct. + return 0; +} + +const RegisterInfo * +RegisterContextFreeBSD_powerpc::GetRegisterInfo() const +{ + //assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc); + llvm_unreachable("Abstract class!"); + return NULL; +} + +uint32_t +RegisterContextFreeBSD_powerpc::GetRegisterCount () const +{ + return 0; +} + +RegisterContextFreeBSD_powerpc32::RegisterContextFreeBSD_powerpc32(const ArchSpec &target_arch) : + RegisterContextFreeBSD_powerpc(target_arch) +{ +} + +RegisterContextFreeBSD_powerpc32::~RegisterContextFreeBSD_powerpc32() +{ +} + +size_t +RegisterContextFreeBSD_powerpc32::GetGPRSize() const +{ + return sizeof(GPR32); +} + +const RegisterInfo * +RegisterContextFreeBSD_powerpc32::GetRegisterInfo() const +{ + //assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc); + return g_register_infos_powerpc32; +} + +uint32_t +RegisterContextFreeBSD_powerpc32::GetRegisterCount () const +{ + return static_cast (sizeof (g_register_infos_powerpc32) / sizeof (g_register_infos_powerpc32 [0])); +} + +RegisterContextFreeBSD_powerpc64::RegisterContextFreeBSD_powerpc64(const ArchSpec &target_arch) : + RegisterContextFreeBSD_powerpc(target_arch) +{ +} + +RegisterContextFreeBSD_powerpc64::~RegisterContextFreeBSD_powerpc64() +{ +} + +size_t +RegisterContextFreeBSD_powerpc64::GetGPRSize() const +{ + return sizeof(GPR64); +} + +const RegisterInfo * +RegisterContextFreeBSD_powerpc64::GetRegisterInfo() const +{ + //assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc); + if (m_target_arch.GetMachine() == llvm::Triple::ppc) + return g_register_infos_powerpc64_32; + return g_register_infos_powerpc64; +} + +uint32_t +RegisterContextFreeBSD_powerpc64::GetRegisterCount () const +{ + return static_cast (sizeof (g_register_infos_powerpc64) / sizeof (g_register_infos_powerpc64 [0])); +} diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h new file mode 100644 index 000000000000..b907fe99b5e0 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h @@ -0,0 +1,66 @@ +//===-- RegisterContextFreeBSD_powerpc.h -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextFreeBSD_powerpc_H_ +#define liblldb_RegisterContextFreeBSD_powerpc_H_ + +#include "RegisterContextPOSIX.h" + +class RegisterContextFreeBSD_powerpc: + public lldb_private::RegisterInfoInterface +{ +public: + RegisterContextFreeBSD_powerpc(const lldb_private::ArchSpec &target_arch); + virtual ~RegisterContextFreeBSD_powerpc(); + + size_t + GetGPRSize() const override; + + const lldb_private::RegisterInfo * + GetRegisterInfo() const override; + + uint32_t + GetRegisterCount() const override; +}; + +class RegisterContextFreeBSD_powerpc32: + public RegisterContextFreeBSD_powerpc +{ +public: + RegisterContextFreeBSD_powerpc32(const lldb_private::ArchSpec &target_arch); + virtual ~RegisterContextFreeBSD_powerpc32(); + + size_t + GetGPRSize() const override; + + const lldb_private::RegisterInfo * + GetRegisterInfo() const override; + + uint32_t + GetRegisterCount() const override; +}; + +class RegisterContextFreeBSD_powerpc64: + public RegisterContextFreeBSD_powerpc +{ +public: + RegisterContextFreeBSD_powerpc64(const lldb_private::ArchSpec &target_arch); + virtual ~RegisterContextFreeBSD_powerpc64(); + + size_t + GetGPRSize() const override; + + const lldb_private::RegisterInfo * + GetRegisterInfo() const override; + + uint32_t + GetRegisterCount() const override; +}; + +#endif diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index b58e6bb607ed..f47d687702ec 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -172,6 +172,21 @@ RegisterContextLLDB::InitializeZerothFrame() m_sym_ctx_valid = true; } + if (m_sym_ctx.symbol) + { + UnwindLogMsg ("with pc value of 0x%" PRIx64 ", symbol name is '%s'", + current_pc, m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.symbol->GetName().AsCString()); + } + else if (m_sym_ctx.function) + { + UnwindLogMsg ("with pc value of 0x%" PRIx64 ", function name is '%s'", + current_pc, m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.function->GetName().AsCString()); + } + else + { + UnwindLogMsg ("with pc value of 0x%" PRIx64 ", no symbol/function name is known.", current_pc); + } + AddressRange addr_range; m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range); @@ -217,7 +232,6 @@ RegisterContextLLDB::InitializeZerothFrame() m_full_unwind_plan_sp = GetFullUnwindPlanForFrame (); UnwindPlan::RowSP active_row; - int cfa_offset = 0; lldb::RegisterKind row_register_kind = eRegisterKindGeneric; if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc)) { @@ -239,18 +253,13 @@ RegisterContextLLDB::InitializeZerothFrame() } - addr_t cfa_regval = LLDB_INVALID_ADDRESS; - if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval)) + if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa)) { UnwindLogMsg ("could not read CFA register for this frame."); m_frame_type = eNotAValidFrame; return; } - cfa_offset = active_row->GetCFAOffset (); - m_cfa = cfa_regval + cfa_offset; - - UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset); UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64 " using %s UnwindPlan", (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa, @@ -294,20 +303,27 @@ RegisterContextLLDB::InitializeNonZerothFrame() if (log) { - UnwindLogMsg ("pc = 0x%16.16" PRIx64, pc); + UnwindLogMsg ("pc = 0x%" PRIx64, pc); addr_t reg_val; if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val)) - UnwindLogMsg ("fp = 0x%16.16" PRIx64, reg_val); + UnwindLogMsg ("fp = 0x%" PRIx64, reg_val); if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val)) - UnwindLogMsg ("sp = 0x%16.16" PRIx64, reg_val); + UnwindLogMsg ("sp = 0x%" PRIx64, reg_val); } - // A pc of 0x0 means it's the end of the stack crawl - if (pc == 0) + // A pc of 0x0 means it's the end of the stack crawl unless we're above a trap handler function + bool above_trap_handler = false; + if (GetNextFrame().get() && GetNextFrame()->IsValid() && GetNextFrame()->IsTrapHandlerFrame()) + above_trap_handler = true; + + if (pc == 0 || pc == 0x1) { - m_frame_type = eNotAValidFrame; - UnwindLogMsg ("this frame has a pc of 0x0"); - return; + if (above_trap_handler == false) + { + m_frame_type = eNotAValidFrame; + UnwindLogMsg ("this frame has a pc of 0x0"); + return; + } } ExecutionContext exe_ctx(m_thread.shared_from_this()); @@ -363,35 +379,31 @@ RegisterContextLLDB::InitializeNonZerothFrame() m_all_registers_available = false; m_current_offset = -1; m_current_offset_backed_up_one = -1; - addr_t cfa_regval = LLDB_INVALID_ADDRESS; RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind (); UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0); if (row.get()) { - uint32_t cfa_regnum = row->GetCFARegister(); - int cfa_offset = row->GetCFAOffset(); - if (!ReadGPRValue (row_register_kind, cfa_regnum, cfa_regval)) + if (!ReadCFAValueForRow (row_register_kind, row, m_cfa)) { UnwindLogMsg ("failed to get cfa value"); if (m_frame_type != eSkipFrame) // don't override eSkipFrame { - m_frame_type = eNormalFrame; + m_frame_type = eNotAValidFrame; } return; } - m_cfa = cfa_regval + cfa_offset; // A couple of sanity checks.. - if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1) + if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == 0 || m_cfa == 1) { UnwindLogMsg ("could not find a valid cfa address"); m_frame_type = eNotAValidFrame; return; } - // cfa_regval should point into the stack memory; if we can query memory region permissions, + // m_cfa should point into the stack memory; if we can query memory region permissions, // see if the memory is allocated & readable. - if (process->GetLoadAddressPermissions(cfa_regval, permissions) + if (process->GetLoadAddressPermissions(m_cfa, permissions) && (permissions & ePermissionsReadable) == 0) { m_frame_type = eNotAValidFrame; @@ -406,6 +418,17 @@ RegisterContextLLDB::InitializeNonZerothFrame() return; } + if (CheckIfLoopingStack ()) + { + TryFallbackUnwindPlan(); + if (CheckIfLoopingStack ()) + { + UnwindLogMsg ("same CFA address as next frame, assuming the unwind is looping - stopping"); + m_frame_type = eNotAValidFrame; + return; + } + } + UnwindLogMsg ("initialized frame cfa is 0x%" PRIx64, (uint64_t) m_cfa); return; } @@ -431,6 +454,21 @@ RegisterContextLLDB::InitializeNonZerothFrame() m_sym_ctx_valid = true; } + if (m_sym_ctx.symbol) + { + UnwindLogMsg ("with pc value of 0x%" PRIx64 ", symbol name is '%s'", + pc, m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.symbol->GetName().AsCString()); + } + else if (m_sym_ctx.function) + { + UnwindLogMsg ("with pc value of 0x%" PRIx64 ", function name is '%s'", + pc, m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.function->GetName().AsCString()); + } + else + { + UnwindLogMsg ("with pc value of 0x%" PRIx64 ", no symbol/function name is known.", pc); + } + AddressRange addr_range; if (!m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range)) { @@ -461,17 +499,22 @@ RegisterContextLLDB::InitializeNonZerothFrame() // to the ABI plugin and consult that. if (decr_pc_and_recompute_addr_range) { - Address temporary_pc(m_current_pc); - temporary_pc.SetOffset(m_current_pc.GetOffset() - 1); - m_sym_ctx.Clear(false); + UnwindLogMsg ("Backing up the pc value of 0x%" PRIx64 " by 1 and re-doing symbol lookup; old symbol was %s", + pc, m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.symbol->GetName().AsCString()); + Address temporary_pc; + temporary_pc.SetLoadAddress (pc - 1, &process->GetTarget()); + m_sym_ctx.Clear (false); m_sym_ctx_valid = false; uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol; - if (pc_module_sp->ResolveSymbolContextForAddress (temporary_pc, resolve_scope, m_sym_ctx) & resolve_scope) + ModuleSP temporary_module_sp = temporary_pc.GetModule(); + if (temporary_module_sp && + temporary_module_sp->ResolveSymbolContextForAddress (temporary_pc, resolve_scope, m_sym_ctx) & resolve_scope) { if (m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range)) m_sym_ctx_valid = true; } + UnwindLogMsg ("Symbol is now %s", m_sym_ctx.symbol == NULL ? "" : m_sym_ctx.symbol->GetName().AsCString()); } // If we were able to find a symbol/function, set addr_range_ptr to the bounds of that symbol/function. @@ -479,13 +522,15 @@ RegisterContextLLDB::InitializeNonZerothFrame() if (addr_range.GetBaseAddress().IsValid()) { m_start_pc = addr_range.GetBaseAddress(); - m_current_offset = m_current_pc.GetOffset() - m_start_pc.GetOffset(); + m_current_offset = pc - m_start_pc.GetLoadAddress (&process->GetTarget()); m_current_offset_backed_up_one = m_current_offset; if (decr_pc_and_recompute_addr_range && m_current_offset_backed_up_one > 0) { m_current_offset_backed_up_one--; if (m_sym_ctx_valid) - m_current_pc.SetOffset(m_current_pc.GetOffset() - 1); + { + m_current_pc.SetLoadAddress (pc - 1, &process->GetTarget()); + } } } else @@ -512,7 +557,6 @@ RegisterContextLLDB::InitializeNonZerothFrame() m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame (); UnwindPlan::RowSP active_row; - int cfa_offset = 0; RegisterKind row_register_kind = eRegisterKindGeneric; // Try to get by with just the fast UnwindPlan if possible - the full UnwindPlan may be expensive to get @@ -553,27 +597,33 @@ RegisterContextLLDB::InitializeNonZerothFrame() return; } - addr_t cfa_regval = LLDB_INVALID_ADDRESS; - if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval)) + if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa)) { UnwindLogMsg ("failed to get cfa reg %d/%d", row_register_kind, active_row->GetCFARegister()); m_frame_type = eNotAValidFrame; return; } - cfa_offset = active_row->GetCFAOffset (); - m_cfa = cfa_regval + cfa_offset; + UnwindLogMsg ("m_cfa = 0x%" PRIx64, m_cfa); - UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset); - - // A couple of sanity checks.. - if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1) + if (CheckIfLoopingStack ()) { - UnwindLogMsg ("could not find a valid cfa address"); - m_frame_type = eNotAValidFrame; - return; + TryFallbackUnwindPlan(); + if (CheckIfLoopingStack ()) + { + UnwindLogMsg ("same CFA address as next frame, assuming the unwind is looping - stopping"); + m_frame_type = eNotAValidFrame; + return; + } } + UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64, + (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa); +} + +bool +RegisterContextLLDB::CheckIfLoopingStack () +{ // If we have a bad stack setup, we can get the same CFA value multiple times -- or even // more devious, we can actually oscillate between two CFA values. Detect that here and // break out to avoid a possible infinite loop in lldb trying to unwind the stack. @@ -581,29 +631,19 @@ RegisterContextLLDB::InitializeNonZerothFrame() addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS; if (GetNextFrame().get() && GetNextFrame()->GetCFA(next_frame_cfa)) { - bool repeating_frames = false; if (next_frame_cfa == m_cfa) { - repeating_frames = true; - } - else - { - if (GetNextFrame()->GetNextFrame() && GetNextFrame()->GetNextFrame()->GetCFA(next_next_frame_cfa) - && next_next_frame_cfa == m_cfa) - { - repeating_frames = true; - } + // We have a loop in the stack unwind + return true; } - if (repeating_frames && abi && abi->FunctionCallsChangeCFA()) + if (GetNextFrame()->GetNextFrame().get() && GetNextFrame()->GetNextFrame()->GetCFA(next_next_frame_cfa) + && next_next_frame_cfa == m_cfa) { - UnwindLogMsg ("same CFA address as next frame, assuming the unwind is looping - stopping"); - m_frame_type = eNotAValidFrame; - return; + // We have a loop in the stack unwind + return true; } } - - UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64, - (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa); + return false; } @@ -715,13 +755,17 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () uint32_t permissions; addr_t current_pc_addr = m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()); if (current_pc_addr == 0 - || (process->GetLoadAddressPermissions (current_pc_addr, permissions) + || (process && + process->GetLoadAddressPermissions (current_pc_addr, permissions) && (permissions & ePermissionsExecutable) == 0)) { - unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - abi->CreateFunctionEntryUnwindPlan(*unwind_plan_sp); - m_frame_type = eNormalFrame; - return unwind_plan_sp; + if (abi) + { + unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); + abi->CreateFunctionEntryUnwindPlan(*unwind_plan_sp); + m_frame_type = eNormalFrame; + return unwind_plan_sp; + } } } @@ -764,10 +808,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () // is properly encoded in the eh_frame section, so prefer that if available. // On other platforms we may need to provide a platform-specific UnwindPlan which encodes the details of // how to unwind out of sigtramp. - if (m_frame_type == eTrapHandlerFrame) + if (m_frame_type == eTrapHandlerFrame && process) { m_fast_unwind_plan_sp.reset(); - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one); + unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc) && unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) { return unwind_plan_sp; @@ -782,7 +826,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () // But there is not. if (process && process->GetDynamicLoader() && process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo (m_sym_ctx)) { - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one); + unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) { UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it", @@ -792,7 +836,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () } // Typically the NonCallSite UnwindPlan is the unwind created by inspecting the assembly language instructions - if (behaves_like_zeroth_frame) + if (behaves_like_zeroth_frame && process) { unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (process->GetTarget(), m_thread, m_current_offset_backed_up_one); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) @@ -812,7 +856,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () } // Typically this is unwind info from an eh_frame section intended for exception handling; only valid at call sites - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one); + if (process) + { + unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one); + } int valid_offset = -1; if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) { @@ -822,7 +869,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () // We'd prefer to use an UnwindPlan intended for call sites when we're at a call site but if we've // struck out on that, fall back to using the non-call-site assembly inspection UnwindPlan if possible. - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (process->GetTarget(), m_thread, m_current_offset_backed_up_one); + if (process) + { + unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (process->GetTarget(), m_thread, m_current_offset_backed_up_one); + } if (unwind_plan_sp && unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) { // We probably have an UnwindPlan created by inspecting assembly instructions, and we probably @@ -908,6 +958,16 @@ RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::Unwind switch (regloc.type) { + case UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext: + { + const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number); + + if (!other_reg_info) + return false; + + success = m_thread.GetRegisterContext()->ReadRegister (other_reg_info, value); + } + break; case UnwindLLDB::RegisterLocation::eRegisterInRegister: { const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number); @@ -962,6 +1022,12 @@ RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindL switch (regloc.type) { + case UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext: + { + const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number); + success = m_thread.GetRegisterContext()->WriteRegister (other_reg_info, value); + } + break; case UnwindLLDB::RegisterLocation::eRegisterInRegister: { const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number); @@ -1004,6 +1070,11 @@ RegisterContextLLDB::IsValid () const return m_frame_type != eNotAValidFrame; } +// After the final stack frame in a stack walk we'll get one invalid (eNotAValidFrame) stack frame -- +// one past the end of the stack walk. But higher-level code will need to tell the differnece between +// "the unwind plan below this frame failed" versus "we successfully completed the stack walk" so +// this method helps to disambiguate that. + bool RegisterContextLLDB::IsTrapHandlerFrame () const { @@ -1056,57 +1127,42 @@ RegisterContextLLDB::IsTrapHandlerSymbol (lldb_private::Process *process, const enum UnwindLLDB::RegisterSearchResult RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc) { + RegisterNumber regnum (m_thread, eRegisterKindLLDB, lldb_regnum); + // Have we already found this register location? if (!m_registers.empty()) { std::map::const_iterator iterator; - iterator = m_registers.find (lldb_regnum); + iterator = m_registers.find (regnum.GetAsKind (eRegisterKindLLDB)); if (iterator != m_registers.end()) { regloc = iterator->second; - UnwindLogMsg ("supplying caller's saved reg %d's location, cached", lldb_regnum); + UnwindLogMsg ("supplying caller's saved %s (%d)'s location, cached", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); return UnwindLLDB::RegisterSearchResult::eRegisterFound; } } - uint32_t sp_regnum = LLDB_INVALID_REGNUM; - uint32_t pc_regnum = LLDB_INVALID_REGNUM; - m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, eRegisterKindLLDB, sp_regnum); - m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, eRegisterKindLLDB, pc_regnum); - - // Are we looking for the CALLER's stack pointer? The stack pointer is defined to be the same as THIS frame's - // CFA so just return the CFA value. This is true on x86-32/x86-64 at least. - if (sp_regnum != LLDB_INVALID_REGNUM && sp_regnum == lldb_regnum) - { - // make sure we won't lose precision copying an addr_t (m_cfa) into a uint64_t (.inferred_value) - assert (sizeof (addr_t) <= sizeof (uint64_t)); - regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; - regloc.location.inferred_value = m_cfa; - m_registers[lldb_regnum] = regloc; - UnwindLogMsg ("supplying caller's stack pointer (%d) value, computed from CFA", lldb_regnum); - return UnwindLLDB::RegisterSearchResult::eRegisterFound; - } - // Look through the available UnwindPlans for the register location. UnwindPlan::Row::RegisterLocation unwindplan_regloc; bool have_unwindplan_regloc = false; - RegisterKind unwindplan_registerkind = (RegisterKind)-1; + RegisterKind unwindplan_registerkind = kNumRegisterKinds; if (m_fast_unwind_plan_sp) { UnwindPlan::RowSP active_row = m_fast_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); unwindplan_registerkind = m_fast_unwind_plan_sp->GetRegisterKind (); - uint32_t row_regnum; - if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum)) + if (regnum.GetAsKind (unwindplan_registerkind) == LLDB_INVALID_REGNUM) { - UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme", - lldb_regnum, (int) unwindplan_registerkind); + UnwindLogMsg ("could not convert lldb regnum %s (%d) into %d RegisterKind reg numbering scheme", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), (int) unwindplan_registerkind); return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; } - if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc)) + if (active_row->GetRegisterInfo (regnum.GetAsKind (unwindplan_registerkind), unwindplan_regloc)) { - UnwindLogMsg ("supplying caller's saved reg %d's location using FastUnwindPlan", lldb_regnum); + UnwindLogMsg ("supplying caller's saved %s (%d)'s location using FastUnwindPlan", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); have_unwindplan_regloc = true; } } @@ -1119,37 +1175,49 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat if (m_full_unwind_plan_sp) { + RegisterNumber pc_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind (); - uint32_t row_regnum; - bool row_register_rewritten_to_return_address_reg = false; + + RegisterNumber return_address_reg; // If we're fetching the saved pc and this UnwindPlan defines a ReturnAddress register (e.g. lr on arm), // look for the return address register number in the UnwindPlan's row. - if (lldb_regnum == pc_regnum && m_full_unwind_plan_sp->GetReturnAddressRegister() != LLDB_INVALID_REGNUM) + if (pc_regnum.IsValid() + && pc_regnum == regnum + && m_full_unwind_plan_sp->GetReturnAddressRegister() != LLDB_INVALID_REGNUM) { - row_regnum = m_full_unwind_plan_sp->GetReturnAddressRegister(); - row_register_rewritten_to_return_address_reg = true; - UnwindLogMsg ("requested caller's saved PC but this UnwindPlan uses a RA reg; getting reg %d instead", - row_regnum); + + return_address_reg.init (m_thread, m_full_unwind_plan_sp->GetRegisterKind(), m_full_unwind_plan_sp->GetReturnAddressRegister()); + regnum = return_address_reg; + UnwindLogMsg ("requested caller's saved PC but this UnwindPlan uses a RA reg; getting %s (%d) instead", + return_address_reg.GetName(), return_address_reg.GetAsKind (eRegisterKindLLDB)); } else { - if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum)) + if (regnum.GetAsKind (unwindplan_registerkind) == LLDB_INVALID_REGNUM) { if (unwindplan_registerkind == eRegisterKindGeneric) - UnwindLogMsg ("could not convert lldb regnum %d into eRegisterKindGeneric reg numbering scheme", lldb_regnum); + { + UnwindLogMsg ("could not convert lldb regnum %s (%d) into eRegisterKindGeneric reg numbering scheme", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); + } else - UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme", - lldb_regnum, (int) unwindplan_registerkind); + { + UnwindLogMsg ("could not convert lldb regnum %s (%d) into %d RegisterKind reg numbering scheme", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), (int) unwindplan_registerkind); + } return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; } } - if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc)) + if (regnum.IsValid() + && active_row->GetRegisterInfo (regnum.GetAsKind (unwindplan_registerkind), unwindplan_regloc)) { have_unwindplan_regloc = true; - UnwindLogMsg ("supplying caller's saved reg %d's location using %s UnwindPlan", lldb_regnum, + UnwindLogMsg ("supplying caller's saved %s (%d)'s location using %s UnwindPlan", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), m_full_unwind_plan_sp->GetSourceName().GetCString()); } @@ -1158,19 +1226,19 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat // Handle this specially. if (have_unwindplan_regloc == false - && row_register_rewritten_to_return_address_reg == true - && IsFrameZero() - && row_regnum != LLDB_INVALID_REGNUM) + && return_address_reg.IsValid() + && IsFrameZero()) { - uint32_t ra_regnum_in_lldb_reg_numbering; - if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (unwindplan_registerkind, row_regnum, eRegisterKindLLDB, ra_regnum_in_lldb_reg_numbering)) + if (return_address_reg.GetAsKind (eRegisterKindLLDB) != LLDB_INVALID_REGNUM) { lldb_private::UnwindLLDB::RegisterLocation new_regloc; - new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; - new_regloc.location.register_number = ra_regnum_in_lldb_reg_numbering; - m_registers[lldb_regnum] = new_regloc; + new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext; + new_regloc.location.register_number = return_address_reg.GetAsKind (eRegisterKindLLDB); + m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = new_regloc; regloc = new_regloc; - UnwindLogMsg ("supplying caller's register %d from the live RegisterContext at frame 0, saved in %d", lldb_regnum, ra_regnum_in_lldb_reg_numbering); + UnwindLogMsg ("supplying caller's register %s (%d) from the live RegisterContext at frame 0, saved in %d", + return_address_reg.GetName(), return_address_reg.GetAsKind (eRegisterKindLLDB), + return_address_reg.GetAsKind (eRegisterKindLLDB)); return UnwindLLDB::RegisterSearchResult::eRegisterFound; } } @@ -1187,13 +1255,12 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat // when we're at a call site location. // arch_default_ra_regnum is the return address register # in the Full UnwindPlan register numbering - uint32_t arch_default_ra_regnum = LLDB_INVALID_REGNUM; - if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, unwindplan_registerkind, arch_default_ra_regnum) - && arch_default_ra_regnum != LLDB_INVALID_REGNUM - && pc_regnum != LLDB_INVALID_REGNUM - && pc_regnum == lldb_regnum + RegisterNumber arch_default_ra_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); + + if (arch_default_ra_regnum.GetAsKind (unwindplan_registerkind) != LLDB_INVALID_REGNUM + && pc_regnum == regnum && unwindplan_regloc.IsInOtherRegister() - && unwindplan_regloc.GetRegisterNumber() == arch_default_ra_regnum + && unwindplan_regloc.GetRegisterNumber() == arch_default_ra_regnum.GetAsKind (unwindplan_registerkind) && m_full_unwind_plan_sp->GetSourcedFromCompiler() != eLazyBoolYes && !m_all_registers_available) { @@ -1201,15 +1268,32 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat m_full_unwind_plan_sp->GetSourceName().GetCString()); // Throw away the full unwindplan; install the arch default unwindplan - if (TryFallbackUnwindPlan()) + if (ForceSwitchToFallbackUnwindPlan()) { - // Now re-fetch the pc value we're searching for - uint32_t arch_default_pc_reg = LLDB_INVALID_REGNUM; + // Update for the possibly new unwind plan + unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind (); UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); - if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, m_full_unwind_plan_sp->GetRegisterKind(), arch_default_pc_reg) - && arch_default_pc_reg != LLDB_INVALID_REGNUM - && active_row - && active_row->GetRegisterInfo (arch_default_pc_reg, unwindplan_regloc)) + + // Sanity check: Verify that we can fetch a pc value and CFA value with this unwind plan + + RegisterNumber arch_default_pc_reg (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + bool can_fetch_pc_value = false; + bool can_fetch_cfa = false; + addr_t cfa_value; + if (active_row) + { + if (arch_default_pc_reg.GetAsKind (unwindplan_registerkind) != LLDB_INVALID_REGNUM + && active_row->GetRegisterInfo (arch_default_pc_reg.GetAsKind (unwindplan_registerkind), unwindplan_regloc)) + { + can_fetch_pc_value = true; + } + if (ReadCFAValueForRow (unwindplan_registerkind, active_row, cfa_value)) + { + can_fetch_cfa = true; + } + } + + if (can_fetch_pc_value && can_fetch_cfa) { have_unwindplan_regloc = true; } @@ -1218,10 +1302,35 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat have_unwindplan_regloc = false; } } + else + { + // We were unable to fall back to another unwind plan + have_unwindplan_regloc = false; + } } } } + if (have_unwindplan_regloc == false) + { + // Did the UnwindPlan fail to give us the caller's stack pointer? + // The stack pointer is defined to be the same as THIS frame's CFA, so return the CFA value as + // the caller's stack pointer. This is true on x86-32/x86-64 at least. + + RegisterNumber sp_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); + if (sp_regnum.GetAsKind (eRegisterKindLLDB) != LLDB_INVALID_REGNUM + && sp_regnum.GetAsKind (eRegisterKindLLDB) == regnum.GetAsKind (eRegisterKindLLDB)) + { + // make sure we won't lose precision copying an addr_t (m_cfa) into a uint64_t (.inferred_value) + assert (sizeof (addr_t) <= sizeof (uint64_t)); + regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; + regloc.location.inferred_value = m_cfa; + m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; + UnwindLogMsg ("supplying caller's stack pointer %s (%d) value, computed from CFA", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterFound; + } + } ExecutionContext exe_ctx(m_thread.shared_from_this()); Process *process = exe_ctx.GetProcessPtr(); @@ -1232,11 +1341,11 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat ABI *abi = process ? process->GetABI().get() : NULL; if (abi) { - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum); + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(regnum.GetAsKind (eRegisterKindLLDB)); if (reg_info && abi->RegisterIsVolatile (reg_info)) { - UnwindLogMsg ("did not supply reg location for %d (%s) because it is volatile", - lldb_regnum, reg_info->name ? reg_info->name : "??"); + UnwindLogMsg ("did not supply reg location for %s (%d) because it is volatile", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile; } } @@ -1245,15 +1354,27 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat { // This is frame 0 - we should return the actual live register context value lldb_private::UnwindLLDB::RegisterLocation new_regloc; - new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; - new_regloc.location.register_number = lldb_regnum; - m_registers[lldb_regnum] = new_regloc; + new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext; + new_regloc.location.register_number = regnum.GetAsKind (eRegisterKindLLDB); + m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = new_regloc; regloc = new_regloc; - UnwindLogMsg ("supplying caller's register %d from the live RegisterContext at frame 0", lldb_regnum); + UnwindLogMsg ("supplying caller's register %s (%d) from the live RegisterContext at frame 0", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); return UnwindLLDB::RegisterSearchResult::eRegisterFound; } else - UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum); + { + std::string unwindplan_name (""); + if (m_full_unwind_plan_sp) + { + unwindplan_name += "via '"; + unwindplan_name += m_full_unwind_plan_sp->GetSourceName().AsCString(); + unwindplan_name += "'"; + } + UnwindLogMsg ("no save location for %s (%d) %s", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), + unwindplan_name.c_str()); + } return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; } @@ -1262,8 +1383,9 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat { lldb_private::UnwindLLDB::RegisterLocation new_regloc; new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterNotSaved; - m_registers[lldb_regnum] = new_regloc; - UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum); + m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = new_regloc; + UnwindLogMsg ("save location for %s (%d) is unspecified, continue searching", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; } @@ -1271,7 +1393,8 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat { if (IsFrameZero ()) { - UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum); + UnwindLogMsg ("could not supply caller's %s (%d) location, IsSame", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; } else @@ -1285,8 +1408,10 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat int offset = unwindplan_regloc.GetOffset(); regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; regloc.location.inferred_value = m_cfa + offset; - m_registers[lldb_regnum] = regloc; - UnwindLogMsg ("supplying caller's register %d, value is CFA plus offset %d", lldb_regnum, offset); + m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; + UnwindLogMsg ("supplying caller's register %s (%d), value is CFA plus offset %d [value is 0x%" PRIx64 "]", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), + offset, regloc.location.inferred_value); return UnwindLLDB::RegisterSearchResult::eRegisterFound; } @@ -1295,24 +1420,29 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat int offset = unwindplan_regloc.GetOffset(); regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation; regloc.location.target_memory_location = m_cfa + offset; - m_registers[lldb_regnum] = regloc; - UnwindLogMsg ("supplying caller's register %d from the stack, saved at CFA plus offset %d", lldb_regnum, offset); + m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; + UnwindLogMsg ("supplying caller's register %s (%d) from the stack, saved at CFA plus offset %d [saved at 0x%" PRIx64 "]", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), + offset, regloc.location.target_memory_location); return UnwindLLDB::RegisterSearchResult::eRegisterFound; } if (unwindplan_regloc.IsInOtherRegister()) { uint32_t unwindplan_regnum = unwindplan_regloc.GetRegisterNumber(); - uint32_t row_regnum_in_lldb; - if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (unwindplan_registerkind, unwindplan_regnum, eRegisterKindLLDB, row_regnum_in_lldb)) + RegisterNumber row_regnum (m_thread, unwindplan_registerkind, unwindplan_regnum); + if (row_regnum.GetAsKind (eRegisterKindLLDB) == LLDB_INVALID_REGNUM) { - UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum); + UnwindLogMsg ("could not supply caller's %s (%d) location - was saved in another reg but couldn't convert that regnum", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; } regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; - regloc.location.register_number = row_regnum_in_lldb; - m_registers[lldb_regnum] = regloc; - UnwindLogMsg ("supplying caller's register %d, saved in register %d", lldb_regnum, row_regnum_in_lldb); + regloc.location.register_number = row_regnum.GetAsKind (eRegisterKindLLDB); + m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; + UnwindLogMsg ("supplying caller's register %s (%d), saved in register %s (%d)", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), + row_regnum.GetName(), row_regnum.GetAsKind (eRegisterKindLLDB)); return UnwindLLDB::RegisterSearchResult::eRegisterFound; } @@ -1334,75 +1464,277 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat { regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; regloc.location.inferred_value = val; - m_registers[lldb_regnum] = regloc; - UnwindLogMsg ("supplying caller's register %d via DWARF expression (IsDWARFExpression)", lldb_regnum); + m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; + UnwindLogMsg ("supplying caller's register %s (%d) via DWARF expression (IsDWARFExpression)", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); return UnwindLLDB::RegisterSearchResult::eRegisterFound; } else { regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation; regloc.location.target_memory_location = val; - m_registers[lldb_regnum] = regloc; - UnwindLogMsg ("supplying caller's register %d via DWARF expression (IsAtDWARFExpression)", lldb_regnum); + m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; + UnwindLogMsg ("supplying caller's register %s (%d) via DWARF expression (IsAtDWARFExpression)", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); return UnwindLLDB::RegisterSearchResult::eRegisterFound; } } - UnwindLogMsg ("tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed", lldb_regnum); + UnwindLogMsg ("tried to use IsDWARFExpression or IsAtDWARFExpression for %s (%d) but failed", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; } - UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum); + UnwindLogMsg ("no save location for %s (%d) in this stack frame", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); // FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported. return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; } -// If the Full unwindplan has been determined to be incorrect, this method will -// replace it with the architecture's default unwindplan, if one is defined. -// It will also find the FuncUnwinders object for this function and replace the -// Full unwind method for the function there so we don't use the errant Full unwindplan -// again in the future of this debug session. -// We're most likely doing this because the Full unwindplan was generated by assembly -// instruction profiling and the profiler got something wrong. +// TryFallbackUnwindPlan() -- this method is a little tricky. +// +// When this is called, the frame above -- the caller frame, the "previous" frame -- +// is invalid or bad. +// +// Instead of stopping the stack walk here, we'll try a different UnwindPlan and see +// if we can get a valid frame above us. +// +// This most often happens when an unwind plan based on assembly instruction inspection +// is not correct -- mostly with hand-written assembly functions or functions where the +// stack frame is set up "out of band", e.g. the kernel saved the register context and +// then called an asynchronous trap handler like _sigtramp. +// +// Often in these cases, if we just do a dumb stack walk we'll get past this tricky +// frame and our usual techniques can continue to be used. bool RegisterContextLLDB::TryFallbackUnwindPlan () { - UnwindPlan::Row::RegisterLocation unwindplan_regloc; - if (m_fallback_unwind_plan_sp.get() == NULL) + if (m_fallback_unwind_plan_sp.get() == nullptr) + return false; + + if (m_full_unwind_plan_sp.get() == nullptr) return false; + if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() + || m_full_unwind_plan_sp->GetSourceName() == m_fallback_unwind_plan_sp->GetSourceName()) + { + return false; + } + + // If a compiler generated unwind plan failed, trying the arch default unwindplan + // isn't going to do any better. + if (m_full_unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) + return false; + + + // Get the caller's pc value and our own CFA value. + // Swap in the fallback unwind plan, re-fetch the caller's pc value and CFA value. + // If they're the same, then the fallback unwind plan provides no benefit. + + RegisterNumber pc_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + + addr_t old_caller_pc_value = LLDB_INVALID_ADDRESS; + addr_t new_caller_pc_value = LLDB_INVALID_ADDRESS; + addr_t old_this_frame_cfa_value = m_cfa; + UnwindLLDB::RegisterLocation regloc; + if (SavedLocationForRegister (pc_regnum.GetAsKind (eRegisterKindLLDB), regloc) == UnwindLLDB::RegisterSearchResult::eRegisterFound) + { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(pc_regnum.GetAsKind (eRegisterKindLLDB)); + if (reg_info) + { + RegisterValue reg_value; + if (ReadRegisterValueFromRegisterLocation (regloc, reg_info, reg_value)) + { + old_caller_pc_value = reg_value.GetAsUInt64(); + } + } + } + + // This is a tricky wrinkle! If SavedLocationForRegister() detects a really impossible + // register location for the full unwind plan, it may call ForceSwitchToFallbackUnwindPlan() + // which in turn replaces the full unwindplan with the fallback... in short, we're done, + // we're using the fallback UnwindPlan. + // We checked if m_fallback_unwind_plan_sp was nullptr at the top -- the only way it + // became nullptr since then is via SavedLocationForRegister(). + if (m_fallback_unwind_plan_sp.get() == nullptr) + return true; + + + // Switch the full UnwindPlan to be the fallback UnwindPlan. If we decide this isn't + // working, we need to restore. + // We'll also need to save & restore the value of the m_cfa ivar. Save is down below a bit in 'old_cfa'. UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp; + addr_t old_cfa = m_cfa; + + m_registers.clear(); + + m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; + UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM) { - FuncUnwindersSP func_unwinders_sp; - if (m_sym_ctx_valid && m_current_pc.IsValid() && m_current_pc.GetModule()) + addr_t new_cfa; + if (!ReadCFAValueForRow (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, new_cfa) + || new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) + { + UnwindLogMsg ("failed to get cfa with fallback unwindplan"); + m_fallback_unwind_plan_sp.reset(); + m_full_unwind_plan_sp = original_full_unwind_plan_sp; + m_cfa = old_cfa; + return false; + } + m_cfa = new_cfa; + + if (SavedLocationForRegister (pc_regnum.GetAsKind (eRegisterKindLLDB), regloc) == UnwindLLDB::RegisterSearchResult::eRegisterFound) { - func_unwinders_sp = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx); - if (func_unwinders_sp) + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(pc_regnum.GetAsKind (eRegisterKindLLDB)); + if (reg_info) { - func_unwinders_sp->InvalidateNonCallSiteUnwindPlan (m_thread); + RegisterValue reg_value; + if (ReadRegisterValueFromRegisterLocation (regloc, reg_info, reg_value)) + { + new_caller_pc_value = reg_value.GetAsUInt64(); + } } } - m_registers.clear(); - m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; - addr_t cfa_regval = LLDB_INVALID_ADDRESS; - if (ReadGPRValue (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row->GetCFARegister(), cfa_regval)) + + + if (new_caller_pc_value == LLDB_INVALID_ADDRESS) { - m_cfa = cfa_regval + active_row->GetCFAOffset (); + UnwindLogMsg ("failed to get a pc value for the caller frame with the fallback unwind plan"); + m_fallback_unwind_plan_sp.reset(); + m_full_unwind_plan_sp = original_full_unwind_plan_sp; + m_cfa = old_cfa; + return false; + } + + if (old_caller_pc_value != LLDB_INVALID_ADDRESS) + { + if (old_caller_pc_value == new_caller_pc_value && new_cfa == old_this_frame_cfa_value) + { + UnwindLogMsg ("fallback unwind plan got the same values for this frame CFA and caller frame pc, not using"); + m_fallback_unwind_plan_sp.reset(); + m_full_unwind_plan_sp = original_full_unwind_plan_sp; + m_cfa = old_cfa; + return false; + } } - UnwindLogMsg ("full unwind plan '%s' has been replaced by architecture default unwind plan '%s' for this function from now on.", - original_full_unwind_plan_sp->GetSourceName().GetCString(), m_fallback_unwind_plan_sp->GetSourceName().GetCString()); + UnwindLogMsg ("trying to unwind from this function with the UnwindPlan '%s' because UnwindPlan '%s' failed.", + m_fallback_unwind_plan_sp->GetSourceName().GetCString(), + original_full_unwind_plan_sp->GetSourceName().GetCString()); + + // We've copied the fallback unwind plan into the full - now clear the fallback. m_fallback_unwind_plan_sp.reset(); } return true; } +bool +RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan () +{ + if (m_fallback_unwind_plan_sp.get() == NULL) + return false; + + if (m_full_unwind_plan_sp.get() == NULL) + return false; + + if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() + || m_full_unwind_plan_sp->GetSourceName() == m_fallback_unwind_plan_sp->GetSourceName()) + { + return false; + } + + UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); + + if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM) + { + addr_t new_cfa; + if (!ReadCFAValueForRow (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, new_cfa) + || new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) + { + UnwindLogMsg ("failed to get cfa with fallback unwindplan"); + m_fallback_unwind_plan_sp.reset(); + return false; + } + + m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; + m_fallback_unwind_plan_sp.reset(); + + m_registers.clear(); + + m_cfa = new_cfa; + + UnwindLogMsg ("switched unconditionally to the fallback unwindplan %s", m_full_unwind_plan_sp->GetSourceName().GetCString()); + return true; + } + return false; +} + +bool +RegisterContextLLDB::ReadCFAValueForRow (lldb::RegisterKind row_register_kind, + const UnwindPlan::RowSP &row, + addr_t &cfa_value) +{ + RegisterNumber cfa_reg (m_thread, row_register_kind, row->GetCFARegister()); + RegisterValue reg_value; + + cfa_value = LLDB_INVALID_ADDRESS; + addr_t cfa_reg_contents; + + if (ReadGPRValue (cfa_reg, cfa_reg_contents)) + { + if (row->GetCFAType() == UnwindPlan::Row::CFAIsRegisterDereferenced) + { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex (cfa_reg.GetAsKind (eRegisterKindLLDB)); + RegisterValue reg_value; + if (reg_info) + { + Error error = ReadRegisterValueFromMemory(reg_info, + cfa_reg_contents, + reg_info->byte_size, + reg_value); + if (error.Success ()) + { + cfa_value = reg_value.GetAsUInt64(); + UnwindLogMsg ("CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64 ", CFA value is 0x%" PRIx64, + cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB), + cfa_reg_contents, cfa_value); + return true; + } + else + { + UnwindLogMsg ("Tried to deref reg %s (%d) [0x%" PRIx64 "] but memory read failed.", + cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB), + cfa_reg_contents); + } + } + } + else + { + if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 || cfa_reg_contents == 1) + { + UnwindLogMsg ("Got an invalid CFA register value - reg %s (%d), value 0x%" PRIx64, + cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB), + cfa_reg_contents); + cfa_reg_contents = LLDB_INVALID_ADDRESS; + return false; + } + cfa_value = cfa_reg_contents + row->GetCFAOffset (); + UnwindLogMsg ("CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64 ", offset is %d", + cfa_value, + cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB), + cfa_reg_contents, row->GetCFAOffset ()); + return true; + } + } + return false; +} + // Retrieve a general purpose register value for THIS frame, as saved by the NEXT frame, i.e. the frame that // this frame called. e.g. // @@ -1471,6 +1803,12 @@ RegisterContextLLDB::ReadGPRValue (lldb::RegisterKind register_kind, uint32_t re return false; } +bool +RegisterContextLLDB::ReadGPRValue (const RegisterNumber ®num, addr_t &value) +{ + return ReadGPRValue (regnum.GetRegisterKind(), regnum.GetRegisterNumber(), value); +} + // Find the value of a register in THIS frame bool @@ -1593,6 +1931,10 @@ RegisterContextLLDB::ReadPC (addr_t& pc) if (!IsValid()) return false; + bool above_trap_handler = false; + if (GetNextFrame().get() && GetNextFrame()->IsValid() && GetNextFrame()->IsTrapHandlerFrame()) + above_trap_handler = true; + if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) { // A pc value of 0 or 1 is impossible in the middle of the stack -- it indicates the end of a stack walk. @@ -1601,6 +1943,7 @@ RegisterContextLLDB::ReadPC (addr_t& pc) // find the bug. if (m_all_registers_available == false + && above_trap_handler == false && (pc == 0 || pc == 1)) { return false; diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.h b/source/Plugins/Process/Utility/RegisterContextLLDB.h index d6ecfeb68caa..5f94a977448d 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.h +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.h @@ -16,6 +16,7 @@ #include "lldb/Target/RegisterContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Utility/RegisterNumber.h" #include "UnwindLLDB.h" namespace lldb_private { @@ -98,6 +99,12 @@ private: // UnwindLLDB needs to pass around references to RegisterLocations friend class UnwindLLDB; + + // Returns true if we have an unwind loop -- the same stack frame unwinding + // multiple times. + bool + CheckIfLoopingStack (); + // Indicates whether this frame is frame zero -- the currently // executing frame -- or not. bool @@ -175,11 +182,30 @@ private: bool TryFallbackUnwindPlan (); + //------------------------------------------------------------------ + /// Switch to the fallback unwind plan unconditionally without any safety + /// checks that it is providing better results than the normal unwind plan. + /// + /// The only time it is valid to call this method is if the full unwindplan is + /// found to be fundamentally incorrect/impossible. + /// + /// Returns true if it was able to install the fallback unwind plan. + //------------------------------------------------------------------ + bool + ForceSwitchToFallbackUnwindPlan (); + // Get the contents of a general purpose (address-size) register for this frame // (usually retrieved from the next frame) bool ReadGPRValue (lldb::RegisterKind register_kind, uint32_t regnum, lldb::addr_t &value); + bool + ReadGPRValue (const RegisterNumber ®_num, lldb::addr_t &value); + + // Get the CFA register for a given frame. + bool + ReadCFAValueForRow (lldb::RegisterKind register_kind, const UnwindPlan::RowSP &row, lldb::addr_t &value); + lldb::UnwindPlanSP GetFastUnwindPlanForFrame (); diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp index e246e715de86..a2ab67438b75 100644 --- a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp +++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp @@ -149,7 +149,8 @@ RegisterContextMacOSXFrameBackchain::ReadRegister (const RegisterInfo *reg_info, // TOOD: need a better way to detect when "long double" types are // the same bytes size as "double" -#if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) && !defined(_MSC_VER) && !defined(__mips__) +#if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) && !defined(_MSC_VER) && \ + !defined(__mips__) && !defined(__powerpc__) && !defined(__ANDROID_NDK__) case sizeof (long double): if (sizeof (long double) == sizeof(uint32_t)) { diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp new file mode 100644 index 000000000000..a9477d583517 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp @@ -0,0 +1,273 @@ +//===-- RegisterContextPOSIX_powerpc.cpp -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Host/Endian.h" +#include "llvm/Support/Compiler.h" + +#include "RegisterContextPOSIX_powerpc.h" +#include "Plugins/Process/elf-core/ProcessElfCore.h" + +using namespace lldb_private; +using namespace lldb; + +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 }, +}; + +bool RegisterContextPOSIX_powerpc::IsGPR(unsigned reg) +{ + return reg <= k_num_gpr_registers_powerpc; // GPR's come first. +} + +bool +RegisterContextPOSIX_powerpc::IsFPR(unsigned reg) +{ + // XXX + return (reg >= k_first_fpr) && (reg <= k_last_fpr); +} + +RegisterContextPOSIX_powerpc::RegisterContextPOSIX_powerpc(Thread &thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info) + : RegisterContext(thread, concrete_frame_idx) +{ + m_register_info_ap.reset(register_info); + + // elf-core yet to support ReadFPR() + ProcessSP base = CalculateProcess(); + if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) + return; +} + +RegisterContextPOSIX_powerpc::~RegisterContextPOSIX_powerpc() +{ +} + +void +RegisterContextPOSIX_powerpc::Invalidate() +{ +} + +void +RegisterContextPOSIX_powerpc::InvalidateAllRegisters() +{ +} + +unsigned +RegisterContextPOSIX_powerpc::GetRegisterOffset(unsigned reg) +{ + assert(reg < k_num_registers_powerpc && "Invalid register number."); + return GetRegisterInfo()[reg].byte_offset; +} + +unsigned +RegisterContextPOSIX_powerpc::GetRegisterSize(unsigned reg) +{ + assert(reg < k_num_registers_powerpc && "Invalid register number."); + return GetRegisterInfo()[reg].byte_size; +} + +size_t +RegisterContextPOSIX_powerpc::GetRegisterCount() +{ + size_t num_registers = k_num_registers_powerpc; + return num_registers; +} + +size_t +RegisterContextPOSIX_powerpc::GetGPRSize() +{ + return m_register_info_ap->GetGPRSize(); +} + +const RegisterInfo * +RegisterContextPOSIX_powerpc::GetRegisterInfo() +{ + // Commonly, this method is overridden and g_register_infos is copied and specialized. + // So, use GetRegisterInfo() rather than g_register_infos in this scope. + return m_register_info_ap->GetRegisterInfo (); +} + +const RegisterInfo * +RegisterContextPOSIX_powerpc::GetRegisterInfoAtIndex(size_t reg) +{ + if (reg < k_num_registers_powerpc) + return &GetRegisterInfo()[reg]; + else + return NULL; +} + +size_t +RegisterContextPOSIX_powerpc::GetRegisterSetCount() +{ + size_t sets = 0; + for (size_t set = 0; set < k_num_register_sets; ++set) + { + if (IsRegisterSetAvailable(set)) + ++sets; + } + + return sets; +} + +const RegisterSet * +RegisterContextPOSIX_powerpc::GetRegisterSet(size_t set) +{ + if (IsRegisterSetAvailable(set)) + return &g_reg_sets_powerpc[set]; + else + return NULL; +} + +const char * +RegisterContextPOSIX_powerpc::GetRegisterName(unsigned reg) +{ + assert(reg < k_num_registers_powerpc && "Invalid register offset."); + return GetRegisterInfo()[reg].name; +} + +lldb::ByteOrder +RegisterContextPOSIX_powerpc::GetByteOrder() +{ + // Get the target process whose privileged thread was used for the register read. + lldb::ByteOrder byte_order = eByteOrderInvalid; + Process *process = CalculateProcess().get(); + + if (process) + byte_order = process->GetByteOrder(); + return byte_order; +} + +bool +RegisterContextPOSIX_powerpc::IsRegisterSetAvailable(size_t set_index) +{ + size_t num_sets = k_num_register_sets; + + return (set_index < num_sets); +} + +// Used when parsing DWARF and EH frame information and any other +// object file sections that contain register numbers in them. +uint32_t +RegisterContextPOSIX_powerpc::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) +{ + const uint32_t num_regs = GetRegisterCount(); + + assert (kind < kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) + { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx); + + if (reg_info->kinds[kind] == num) + return reg_idx; + } + + return LLDB_INVALID_REGNUM; +} + diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h new file mode 100644 index 000000000000..3194c3968c98 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h @@ -0,0 +1,173 @@ +//===-- RegisterContextPOSIX_powerpc.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextPOSIX_powerpc_H_ +#define liblldb_RegisterContextPOSIX_powerpc_H_ + +#include "lldb/Core/Log.h" +#include "RegisterContextPOSIX.h" +#include "RegisterContext_powerpc.h" + +class ProcessMonitor; + +// --------------------------------------------------------------------------- +// Internal codes for all powerpc registers. +// --------------------------------------------------------------------------- +enum +{ + k_first_gpr_powerpc, + gpr_r0_powerpc = k_first_gpr_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, + k_last_gpr_powerpc = gpr_pc_powerpc, + + k_first_fpr, + fpr_f0_powerpc = k_first_fpr, + 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, + k_last_fpr = fpr_fpscr_powerpc, + + k_num_registers_powerpc, + k_num_gpr_registers_powerpc = k_last_gpr_powerpc - k_first_gpr_powerpc + 1, + k_num_fpr_registers_powerpc = k_last_fpr - k_first_fpr + 1, +}; + +class RegisterContextPOSIX_powerpc + : public lldb_private::RegisterContext +{ +public: + RegisterContextPOSIX_powerpc (lldb_private::Thread &thread, + uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info); + + ~RegisterContextPOSIX_powerpc(); + + void + Invalidate(); + + void + InvalidateAllRegisters(); + + size_t + GetRegisterCount(); + + virtual size_t + GetGPRSize(); + + virtual unsigned + GetRegisterSize(unsigned reg); + + virtual unsigned + GetRegisterOffset(unsigned reg); + + const lldb_private::RegisterInfo * + GetRegisterInfoAtIndex(size_t reg); + + size_t + GetRegisterSetCount(); + + const lldb_private::RegisterSet * + GetRegisterSet(size_t set); + + const char * + GetRegisterName(unsigned reg); + + uint32_t + ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num); + +protected: + uint64_t m_gpr_powerpc[k_num_gpr_registers_powerpc]; // general purpose registers. + std::unique_ptr m_register_info_ap; // Register Info Interface (FreeBSD or Linux) + + // Determines if an extended register set is supported on the processor running the inferior process. + virtual bool + IsRegisterSetAvailable(size_t set_index); + + virtual const lldb_private::RegisterInfo * + GetRegisterInfo(); + + bool + IsGPR(unsigned reg); + + bool + IsFPR(unsigned reg); + + lldb::ByteOrder GetByteOrder(); + + virtual bool ReadGPR() = 0; + virtual bool ReadFPR() = 0; + virtual bool WriteGPR() = 0; + virtual bool WriteFPR() = 0; +}; + +#endif // #ifndef liblldb_RegisterContextPOSIX_powerpc_H_ diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp index 2925a33a1690..77b6385da8bd 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp @@ -30,96 +30,96 @@ using namespace lldb; const uint32_t g_gpr_regnums_i386[] = { - gpr_eax_i386, - gpr_ebx_i386, - gpr_ecx_i386, - gpr_edx_i386, - gpr_edi_i386, - gpr_esi_i386, - gpr_ebp_i386, - gpr_esp_i386, - gpr_eip_i386, - gpr_eflags_i386, - gpr_cs_i386, - gpr_fs_i386, - gpr_gs_i386, - gpr_ss_i386, - gpr_ds_i386, - gpr_es_i386, - gpr_ax_i386, - gpr_bx_i386, - gpr_cx_i386, - gpr_dx_i386, - gpr_di_i386, - gpr_si_i386, - gpr_bp_i386, - gpr_sp_i386, - gpr_ah_i386, - gpr_bh_i386, - gpr_ch_i386, - gpr_dh_i386, - gpr_al_i386, - gpr_bl_i386, - gpr_cl_i386, - gpr_dl_i386, + lldb_eax_i386, + lldb_ebx_i386, + lldb_ecx_i386, + lldb_edx_i386, + lldb_edi_i386, + lldb_esi_i386, + lldb_ebp_i386, + lldb_esp_i386, + lldb_eip_i386, + lldb_eflags_i386, + lldb_cs_i386, + lldb_fs_i386, + lldb_gs_i386, + lldb_ss_i386, + lldb_ds_i386, + lldb_es_i386, + lldb_ax_i386, + lldb_bx_i386, + lldb_cx_i386, + lldb_dx_i386, + lldb_di_i386, + lldb_si_i386, + lldb_bp_i386, + lldb_sp_i386, + lldb_ah_i386, + lldb_bh_i386, + lldb_ch_i386, + lldb_dh_i386, + lldb_al_i386, + lldb_bl_i386, + lldb_cl_i386, + lldb_dl_i386, LLDB_INVALID_REGNUM, // Register sets must be terminated with LLDB_INVALID_REGNUM. }; static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) - 1 == k_num_gpr_registers_i386, "g_gpr_regnums_i386 has wrong number of register infos"); const uint32_t -g_fpu_regnums_i386[] = -{ - fpu_fctrl_i386, - fpu_fstat_i386, - fpu_ftag_i386, - fpu_fop_i386, - fpu_fiseg_i386, - fpu_fioff_i386, - fpu_foseg_i386, - fpu_fooff_i386, - fpu_mxcsr_i386, - fpu_mxcsrmask_i386, - fpu_st0_i386, - fpu_st1_i386, - fpu_st2_i386, - fpu_st3_i386, - fpu_st4_i386, - fpu_st5_i386, - fpu_st6_i386, - fpu_st7_i386, - fpu_mm0_i386, - fpu_mm1_i386, - fpu_mm2_i386, - fpu_mm3_i386, - fpu_mm4_i386, - fpu_mm5_i386, - fpu_mm6_i386, - fpu_mm7_i386, - fpu_xmm0_i386, - fpu_xmm1_i386, - fpu_xmm2_i386, - fpu_xmm3_i386, - fpu_xmm4_i386, - fpu_xmm5_i386, - fpu_xmm6_i386, - fpu_xmm7_i386, +g_lldb_regnums_i386[] = +{ + lldb_fctrl_i386, + lldb_fstat_i386, + lldb_ftag_i386, + lldb_fop_i386, + lldb_fiseg_i386, + lldb_fioff_i386, + lldb_foseg_i386, + lldb_fooff_i386, + lldb_mxcsr_i386, + lldb_mxcsrmask_i386, + lldb_st0_i386, + lldb_st1_i386, + lldb_st2_i386, + lldb_st3_i386, + lldb_st4_i386, + lldb_st5_i386, + lldb_st6_i386, + lldb_st7_i386, + lldb_mm0_i386, + lldb_mm1_i386, + lldb_mm2_i386, + lldb_mm3_i386, + lldb_mm4_i386, + lldb_mm5_i386, + lldb_mm6_i386, + lldb_mm7_i386, + lldb_xmm0_i386, + lldb_xmm1_i386, + lldb_xmm2_i386, + lldb_xmm3_i386, + lldb_xmm4_i386, + lldb_xmm5_i386, + lldb_xmm6_i386, + lldb_xmm7_i386, LLDB_INVALID_REGNUM // Register sets must be terminated with LLDB_INVALID_REGNUM. }; -static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) - 1 == k_num_fpr_registers_i386, - "g_fpu_regnums_i386 has wrong number of register infos"); +static_assert((sizeof(g_lldb_regnums_i386) / sizeof(g_lldb_regnums_i386[0])) - 1 == k_num_fpr_registers_i386, + "g_lldb_regnums_i386 has wrong number of register infos"); const uint32_t g_avx_regnums_i386[] = { - fpu_ymm0_i386, - fpu_ymm1_i386, - fpu_ymm2_i386, - fpu_ymm3_i386, - fpu_ymm4_i386, - fpu_ymm5_i386, - fpu_ymm6_i386, - fpu_ymm7_i386, + lldb_ymm0_i386, + lldb_ymm1_i386, + lldb_ymm2_i386, + lldb_ymm3_i386, + lldb_ymm4_i386, + lldb_ymm5_i386, + lldb_ymm6_i386, + lldb_ymm7_i386, LLDB_INVALID_REGNUM // Register sets must be terminated with LLDB_INVALID_REGNUM. }; static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - 1 == k_num_avx_registers_i386, @@ -128,212 +128,212 @@ static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - 1 = static const uint32_t g_gpr_regnums_x86_64[] = { - gpr_rax_x86_64, - gpr_rbx_x86_64, - gpr_rcx_x86_64, - gpr_rdx_x86_64, - gpr_rdi_x86_64, - gpr_rsi_x86_64, - gpr_rbp_x86_64, - gpr_rsp_x86_64, - gpr_r8_x86_64, - gpr_r9_x86_64, - gpr_r10_x86_64, - gpr_r11_x86_64, - gpr_r12_x86_64, - gpr_r13_x86_64, - gpr_r14_x86_64, - gpr_r15_x86_64, - gpr_rip_x86_64, - gpr_rflags_x86_64, - gpr_cs_x86_64, - gpr_fs_x86_64, - gpr_gs_x86_64, - gpr_ss_x86_64, - gpr_ds_x86_64, - gpr_es_x86_64, - gpr_eax_x86_64, - gpr_ebx_x86_64, - gpr_ecx_x86_64, - gpr_edx_x86_64, - gpr_edi_x86_64, - gpr_esi_x86_64, - gpr_ebp_x86_64, - gpr_esp_x86_64, - gpr_r8d_x86_64, // Low 32 bits or r8 - gpr_r9d_x86_64, // Low 32 bits or r9 - gpr_r10d_x86_64, // Low 32 bits or r10 - gpr_r11d_x86_64, // Low 32 bits or r11 - gpr_r12d_x86_64, // Low 32 bits or r12 - gpr_r13d_x86_64, // Low 32 bits or r13 - gpr_r14d_x86_64, // Low 32 bits or r14 - gpr_r15d_x86_64, // Low 32 bits or r15 - gpr_ax_x86_64, - gpr_bx_x86_64, - gpr_cx_x86_64, - gpr_dx_x86_64, - gpr_di_x86_64, - gpr_si_x86_64, - gpr_bp_x86_64, - gpr_sp_x86_64, - gpr_r8w_x86_64, // Low 16 bits or r8 - gpr_r9w_x86_64, // Low 16 bits or r9 - gpr_r10w_x86_64, // Low 16 bits or r10 - gpr_r11w_x86_64, // Low 16 bits or r11 - gpr_r12w_x86_64, // Low 16 bits or r12 - gpr_r13w_x86_64, // Low 16 bits or r13 - gpr_r14w_x86_64, // Low 16 bits or r14 - gpr_r15w_x86_64, // Low 16 bits or r15 - gpr_ah_x86_64, - gpr_bh_x86_64, - gpr_ch_x86_64, - gpr_dh_x86_64, - gpr_al_x86_64, - gpr_bl_x86_64, - gpr_cl_x86_64, - gpr_dl_x86_64, - gpr_dil_x86_64, - gpr_sil_x86_64, - gpr_bpl_x86_64, - gpr_spl_x86_64, - gpr_r8l_x86_64, // Low 8 bits or r8 - gpr_r9l_x86_64, // Low 8 bits or r9 - gpr_r10l_x86_64, // Low 8 bits or r10 - gpr_r11l_x86_64, // Low 8 bits or r11 - gpr_r12l_x86_64, // Low 8 bits or r12 - gpr_r13l_x86_64, // Low 8 bits or r13 - gpr_r14l_x86_64, // Low 8 bits or r14 - gpr_r15l_x86_64, // Low 8 bits or r15 + lldb_rax_x86_64, + lldb_rbx_x86_64, + lldb_rcx_x86_64, + lldb_rdx_x86_64, + lldb_rdi_x86_64, + lldb_rsi_x86_64, + lldb_rbp_x86_64, + lldb_rsp_x86_64, + lldb_r8_x86_64, + lldb_r9_x86_64, + lldb_r10_x86_64, + lldb_r11_x86_64, + lldb_r12_x86_64, + lldb_r13_x86_64, + lldb_r14_x86_64, + lldb_r15_x86_64, + lldb_rip_x86_64, + lldb_rflags_x86_64, + lldb_cs_x86_64, + lldb_fs_x86_64, + lldb_gs_x86_64, + lldb_ss_x86_64, + lldb_ds_x86_64, + lldb_es_x86_64, + lldb_eax_x86_64, + lldb_ebx_x86_64, + lldb_ecx_x86_64, + lldb_edx_x86_64, + lldb_edi_x86_64, + lldb_esi_x86_64, + lldb_ebp_x86_64, + lldb_esp_x86_64, + lldb_r8d_x86_64, // Low 32 bits or r8 + lldb_r9d_x86_64, // Low 32 bits or r9 + lldb_r10d_x86_64, // Low 32 bits or r10 + lldb_r11d_x86_64, // Low 32 bits or r11 + lldb_r12d_x86_64, // Low 32 bits or r12 + lldb_r13d_x86_64, // Low 32 bits or r13 + lldb_r14d_x86_64, // Low 32 bits or r14 + lldb_r15d_x86_64, // Low 32 bits or r15 + lldb_ax_x86_64, + lldb_bx_x86_64, + lldb_cx_x86_64, + lldb_dx_x86_64, + lldb_di_x86_64, + lldb_si_x86_64, + lldb_bp_x86_64, + lldb_sp_x86_64, + lldb_r8w_x86_64, // Low 16 bits or r8 + lldb_r9w_x86_64, // Low 16 bits or r9 + lldb_r10w_x86_64, // Low 16 bits or r10 + lldb_r11w_x86_64, // Low 16 bits or r11 + lldb_r12w_x86_64, // Low 16 bits or r12 + lldb_r13w_x86_64, // Low 16 bits or r13 + lldb_r14w_x86_64, // Low 16 bits or r14 + lldb_r15w_x86_64, // Low 16 bits or r15 + lldb_ah_x86_64, + lldb_bh_x86_64, + lldb_ch_x86_64, + lldb_dh_x86_64, + lldb_al_x86_64, + lldb_bl_x86_64, + lldb_cl_x86_64, + lldb_dl_x86_64, + lldb_dil_x86_64, + lldb_sil_x86_64, + lldb_bpl_x86_64, + lldb_spl_x86_64, + lldb_r8l_x86_64, // Low 8 bits or r8 + lldb_r9l_x86_64, // Low 8 bits or r9 + lldb_r10l_x86_64, // Low 8 bits or r10 + lldb_r11l_x86_64, // Low 8 bits or r11 + lldb_r12l_x86_64, // Low 8 bits or r12 + lldb_r13l_x86_64, // Low 8 bits or r13 + lldb_r14l_x86_64, // Low 8 bits or r14 + lldb_r15l_x86_64, // Low 8 bits or r15 LLDB_INVALID_REGNUM // Register sets must be terminated with LLDB_INVALID_REGNUM. }; static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) - 1 == k_num_gpr_registers_x86_64, "g_gpr_regnums_x86_64 has wrong number of register infos"); static const uint32_t -g_fpu_regnums_x86_64[] = -{ - fpu_fctrl_x86_64, - fpu_fstat_x86_64, - fpu_ftag_x86_64, - fpu_fop_x86_64, - fpu_fiseg_x86_64, - fpu_fioff_x86_64, - fpu_foseg_x86_64, - fpu_fooff_x86_64, - fpu_mxcsr_x86_64, - fpu_mxcsrmask_x86_64, - fpu_st0_x86_64, - fpu_st1_x86_64, - fpu_st2_x86_64, - fpu_st3_x86_64, - fpu_st4_x86_64, - fpu_st5_x86_64, - fpu_st6_x86_64, - fpu_st7_x86_64, - fpu_mm0_x86_64, - fpu_mm1_x86_64, - fpu_mm2_x86_64, - fpu_mm3_x86_64, - fpu_mm4_x86_64, - fpu_mm5_x86_64, - fpu_mm6_x86_64, - fpu_mm7_x86_64, - fpu_xmm0_x86_64, - fpu_xmm1_x86_64, - fpu_xmm2_x86_64, - fpu_xmm3_x86_64, - fpu_xmm4_x86_64, - fpu_xmm5_x86_64, - fpu_xmm6_x86_64, - fpu_xmm7_x86_64, - fpu_xmm8_x86_64, - fpu_xmm9_x86_64, - fpu_xmm10_x86_64, - fpu_xmm11_x86_64, - fpu_xmm12_x86_64, - fpu_xmm13_x86_64, - fpu_xmm14_x86_64, - fpu_xmm15_x86_64, +g_lldb_regnums_x86_64[] = +{ + lldb_fctrl_x86_64, + lldb_fstat_x86_64, + lldb_ftag_x86_64, + lldb_fop_x86_64, + lldb_fiseg_x86_64, + lldb_fioff_x86_64, + lldb_foseg_x86_64, + lldb_fooff_x86_64, + lldb_mxcsr_x86_64, + lldb_mxcsrmask_x86_64, + lldb_st0_x86_64, + lldb_st1_x86_64, + lldb_st2_x86_64, + lldb_st3_x86_64, + lldb_st4_x86_64, + lldb_st5_x86_64, + lldb_st6_x86_64, + lldb_st7_x86_64, + lldb_mm0_x86_64, + lldb_mm1_x86_64, + lldb_mm2_x86_64, + lldb_mm3_x86_64, + lldb_mm4_x86_64, + lldb_mm5_x86_64, + lldb_mm6_x86_64, + lldb_mm7_x86_64, + lldb_xmm0_x86_64, + lldb_xmm1_x86_64, + lldb_xmm2_x86_64, + lldb_xmm3_x86_64, + lldb_xmm4_x86_64, + lldb_xmm5_x86_64, + lldb_xmm6_x86_64, + lldb_xmm7_x86_64, + lldb_xmm8_x86_64, + lldb_xmm9_x86_64, + lldb_xmm10_x86_64, + lldb_xmm11_x86_64, + lldb_xmm12_x86_64, + lldb_xmm13_x86_64, + lldb_xmm14_x86_64, + lldb_xmm15_x86_64, LLDB_INVALID_REGNUM // Register sets must be terminated with LLDB_INVALID_REGNUM. }; -static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) - 1 == k_num_fpr_registers_x86_64, - "g_fpu_regnums_x86_64 has wrong number of register infos"); +static_assert((sizeof(g_lldb_regnums_x86_64) / sizeof(g_lldb_regnums_x86_64[0])) - 1 == k_num_fpr_registers_x86_64, + "g_lldb_regnums_x86_64 has wrong number of register infos"); static const uint32_t g_avx_regnums_x86_64[] = { - fpu_ymm0_x86_64, - fpu_ymm1_x86_64, - fpu_ymm2_x86_64, - fpu_ymm3_x86_64, - fpu_ymm4_x86_64, - fpu_ymm5_x86_64, - fpu_ymm6_x86_64, - fpu_ymm7_x86_64, - fpu_ymm8_x86_64, - fpu_ymm9_x86_64, - fpu_ymm10_x86_64, - fpu_ymm11_x86_64, - fpu_ymm12_x86_64, - fpu_ymm13_x86_64, - fpu_ymm14_x86_64, - fpu_ymm15_x86_64, + lldb_ymm0_x86_64, + lldb_ymm1_x86_64, + lldb_ymm2_x86_64, + lldb_ymm3_x86_64, + lldb_ymm4_x86_64, + lldb_ymm5_x86_64, + lldb_ymm6_x86_64, + lldb_ymm7_x86_64, + lldb_ymm8_x86_64, + lldb_ymm9_x86_64, + lldb_ymm10_x86_64, + lldb_ymm11_x86_64, + lldb_ymm12_x86_64, + lldb_ymm13_x86_64, + lldb_ymm14_x86_64, + lldb_ymm15_x86_64, LLDB_INVALID_REGNUM // Register sets must be terminated with LLDB_INVALID_REGNUM. }; static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) - 1 == k_num_avx_registers_x86_64, "g_avx_regnums_x86_64 has wrong number of register infos"); -uint32_t RegisterContextPOSIX_x86::g_contained_eax[] = { gpr_eax_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_ebx[] = { gpr_ebx_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_ecx[] = { gpr_ecx_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_edx[] = { gpr_edx_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_edi[] = { gpr_edi_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_esi[] = { gpr_esi_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_ebp[] = { gpr_ebp_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_esp[] = { gpr_esp_i386, LLDB_INVALID_REGNUM }; - -uint32_t RegisterContextPOSIX_x86::g_invalidate_eax[] = { gpr_eax_i386, gpr_ax_i386, gpr_ah_i386, gpr_al_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_ebx[] = { gpr_ebx_i386, gpr_bx_i386, gpr_bh_i386, gpr_bl_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_ecx[] = { gpr_ecx_i386, gpr_cx_i386, gpr_ch_i386, gpr_cl_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_edx[] = { gpr_edx_i386, gpr_dx_i386, gpr_dh_i386, gpr_dl_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_edi[] = { gpr_edi_i386, gpr_di_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_esi[] = { gpr_esi_i386, gpr_si_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_ebp[] = { gpr_ebp_i386, gpr_bp_i386, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_esp[] = { gpr_esp_i386, gpr_sp_i386, LLDB_INVALID_REGNUM }; - -uint32_t RegisterContextPOSIX_x86::g_contained_rax[] = { gpr_rax_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_rbx[] = { gpr_rbx_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_rcx[] = { gpr_rcx_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_rdx[] = { gpr_rdx_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_rdi[] = { gpr_rdi_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_rsi[] = { gpr_rsi_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_rbp[] = { gpr_rbp_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_rsp[] = { gpr_rsp_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r8[] = { gpr_r8_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r9[] = { gpr_r9_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r10[] = { gpr_r10_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r11[] = { gpr_r11_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r12[] = { gpr_r12_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r13[] = { gpr_r13_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r14[] = { gpr_r14_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_contained_r15[] = { gpr_r15_x86_64, LLDB_INVALID_REGNUM }; - -uint32_t RegisterContextPOSIX_x86::g_invalidate_rax[] = { gpr_rax_x86_64, gpr_eax_x86_64, gpr_ax_x86_64, gpr_ah_x86_64, gpr_al_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_rbx[] = { gpr_rbx_x86_64, gpr_ebx_x86_64, gpr_bx_x86_64, gpr_bh_x86_64, gpr_bl_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_rcx[] = { gpr_rcx_x86_64, gpr_ecx_x86_64, gpr_cx_x86_64, gpr_ch_x86_64, gpr_cl_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_rdx[] = { gpr_rdx_x86_64, gpr_edx_x86_64, gpr_dx_x86_64, gpr_dh_x86_64, gpr_dl_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_rdi[] = { gpr_rdi_x86_64, gpr_edi_x86_64, gpr_di_x86_64, gpr_dil_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_rsi[] = { gpr_rsi_x86_64, gpr_esi_x86_64, gpr_si_x86_64, gpr_sil_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_rbp[] = { gpr_rbp_x86_64, gpr_ebp_x86_64, gpr_bp_x86_64, gpr_bpl_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_rsp[] = { gpr_rsp_x86_64, gpr_esp_x86_64, gpr_sp_x86_64, gpr_spl_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r8[] = { gpr_r8_x86_64, gpr_r8d_x86_64, gpr_r8w_x86_64, gpr_r8l_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r9[] = { gpr_r9_x86_64, gpr_r9d_x86_64, gpr_r9w_x86_64, gpr_r9l_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r10[] = { gpr_r10_x86_64, gpr_r10d_x86_64, gpr_r10w_x86_64, gpr_r10l_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r11[] = { gpr_r11_x86_64, gpr_r11d_x86_64, gpr_r11w_x86_64, gpr_r11l_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r12[] = { gpr_r12_x86_64, gpr_r12d_x86_64, gpr_r12w_x86_64, gpr_r12l_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r13[] = { gpr_r13_x86_64, gpr_r13d_x86_64, gpr_r13w_x86_64, gpr_r13l_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r14[] = { gpr_r14_x86_64, gpr_r14d_x86_64, gpr_r14w_x86_64, gpr_r14l_x86_64, LLDB_INVALID_REGNUM }; -uint32_t RegisterContextPOSIX_x86::g_invalidate_r15[] = { gpr_r15_x86_64, gpr_r15d_x86_64, gpr_r15w_x86_64, gpr_r15l_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_eax[] = { lldb_eax_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_ebx[] = { lldb_ebx_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_ecx[] = { lldb_ecx_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_edx[] = { lldb_edx_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_edi[] = { lldb_edi_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_esi[] = { lldb_esi_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_ebp[] = { lldb_ebp_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_esp[] = { lldb_esp_i386, LLDB_INVALID_REGNUM }; + +uint32_t RegisterContextPOSIX_x86::g_invalidate_eax[] = { lldb_eax_i386, lldb_ax_i386, lldb_ah_i386, lldb_al_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_ebx[] = { lldb_ebx_i386, lldb_bx_i386, lldb_bh_i386, lldb_bl_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_ecx[] = { lldb_ecx_i386, lldb_cx_i386, lldb_ch_i386, lldb_cl_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_edx[] = { lldb_edx_i386, lldb_dx_i386, lldb_dh_i386, lldb_dl_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_edi[] = { lldb_edi_i386, lldb_di_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_esi[] = { lldb_esi_i386, lldb_si_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_ebp[] = { lldb_ebp_i386, lldb_bp_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_esp[] = { lldb_esp_i386, lldb_sp_i386, LLDB_INVALID_REGNUM }; + +uint32_t RegisterContextPOSIX_x86::g_contained_rax[] = { lldb_rax_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_rbx[] = { lldb_rbx_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_rcx[] = { lldb_rcx_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_rdx[] = { lldb_rdx_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_rdi[] = { lldb_rdi_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_rsi[] = { lldb_rsi_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_rbp[] = { lldb_rbp_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_rsp[] = { lldb_rsp_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r8[] = { lldb_r8_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r9[] = { lldb_r9_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r10[] = { lldb_r10_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r11[] = { lldb_r11_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r12[] = { lldb_r12_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r13[] = { lldb_r13_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r14[] = { lldb_r14_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r15[] = { lldb_r15_x86_64, LLDB_INVALID_REGNUM }; + +uint32_t RegisterContextPOSIX_x86::g_invalidate_rax[] = { lldb_rax_x86_64, lldb_eax_x86_64, lldb_ax_x86_64, lldb_ah_x86_64, lldb_al_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rbx[] = { lldb_rbx_x86_64, lldb_ebx_x86_64, lldb_bx_x86_64, lldb_bh_x86_64, lldb_bl_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rcx[] = { lldb_rcx_x86_64, lldb_ecx_x86_64, lldb_cx_x86_64, lldb_ch_x86_64, lldb_cl_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rdx[] = { lldb_rdx_x86_64, lldb_edx_x86_64, lldb_dx_x86_64, lldb_dh_x86_64, lldb_dl_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rdi[] = { lldb_rdi_x86_64, lldb_edi_x86_64, lldb_di_x86_64, lldb_dil_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rsi[] = { lldb_rsi_x86_64, lldb_esi_x86_64, lldb_si_x86_64, lldb_sil_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rbp[] = { lldb_rbp_x86_64, lldb_ebp_x86_64, lldb_bp_x86_64, lldb_bpl_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rsp[] = { lldb_rsp_x86_64, lldb_esp_x86_64, lldb_sp_x86_64, lldb_spl_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r8[] = { lldb_r8_x86_64, lldb_r8d_x86_64, lldb_r8w_x86_64, lldb_r8l_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r9[] = { lldb_r9_x86_64, lldb_r9d_x86_64, lldb_r9w_x86_64, lldb_r9l_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r10[] = { lldb_r10_x86_64, lldb_r10d_x86_64, lldb_r10w_x86_64, lldb_r10l_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r11[] = { lldb_r11_x86_64, lldb_r11d_x86_64, lldb_r11w_x86_64, lldb_r11l_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r12[] = { lldb_r12_x86_64, lldb_r12d_x86_64, lldb_r12w_x86_64, lldb_r12l_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r13[] = { lldb_r13_x86_64, lldb_r13d_x86_64, lldb_r13w_x86_64, lldb_r13l_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r14[] = { lldb_r14_x86_64, lldb_r14d_x86_64, lldb_r14w_x86_64, lldb_r14l_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r15[] = { lldb_r15_x86_64, lldb_r15d_x86_64, lldb_r15w_x86_64, lldb_r15l_x86_64, LLDB_INVALID_REGNUM }; // Number of register sets provided by this context. enum @@ -346,7 +346,7 @@ static const RegisterSet g_reg_sets_i386[k_num_register_sets] = { { "General Purpose Registers", "gpr", k_num_gpr_registers_i386, g_gpr_regnums_i386 }, - { "Floating Point Registers", "fpu", k_num_fpr_registers_i386, g_fpu_regnums_i386 }, + { "Floating Point Registers", "fpu", k_num_fpr_registers_i386, g_lldb_regnums_i386 }, { "Advanced Vector Extensions", "avx", k_num_avx_registers_i386, g_avx_regnums_i386 } }; @@ -354,7 +354,7 @@ static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = { { "General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, g_gpr_regnums_x86_64 }, - { "Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, g_fpu_regnums_x86_64 }, + { "Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, g_lldb_regnums_x86_64 }, { "Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, g_avx_regnums_x86_64 } }; @@ -399,16 +399,16 @@ RegisterContextPOSIX_x86::RegisterContextPOSIX_x86(Thread &thread, m_reg_info.last_gpr = k_last_gpr_i386; m_reg_info.first_fpr = k_first_fpr_i386; m_reg_info.last_fpr = k_last_fpr_i386; - m_reg_info.first_st = fpu_st0_i386; - m_reg_info.last_st = fpu_st7_i386; - m_reg_info.first_mm = fpu_mm0_i386; - m_reg_info.last_mm = fpu_mm7_i386; - m_reg_info.first_xmm = fpu_xmm0_i386; - m_reg_info.last_xmm = fpu_xmm7_i386; - m_reg_info.first_ymm = fpu_ymm0_i386; - m_reg_info.last_ymm = fpu_ymm7_i386; - m_reg_info.first_dr = dr0_i386; - m_reg_info.gpr_flags = gpr_eflags_i386; + m_reg_info.first_st = lldb_st0_i386; + m_reg_info.last_st = lldb_st7_i386; + m_reg_info.first_mm = lldb_mm0_i386; + m_reg_info.last_mm = lldb_mm7_i386; + m_reg_info.first_xmm = lldb_xmm0_i386; + m_reg_info.last_xmm = lldb_xmm7_i386; + m_reg_info.first_ymm = lldb_ymm0_i386; + m_reg_info.last_ymm = lldb_ymm7_i386; + m_reg_info.first_dr = lldb_dr0_i386; + m_reg_info.gpr_flags = lldb_eflags_i386; break; case llvm::Triple::x86_64: m_reg_info.num_registers = k_num_registers_x86_64; @@ -418,16 +418,16 @@ RegisterContextPOSIX_x86::RegisterContextPOSIX_x86(Thread &thread, m_reg_info.last_gpr = k_last_gpr_x86_64; m_reg_info.first_fpr = k_first_fpr_x86_64; m_reg_info.last_fpr = k_last_fpr_x86_64; - m_reg_info.first_st = fpu_st0_x86_64; - m_reg_info.last_st = fpu_st7_x86_64; - m_reg_info.first_mm = fpu_mm0_x86_64; - m_reg_info.last_mm = fpu_mm7_x86_64; - m_reg_info.first_xmm = fpu_xmm0_x86_64; - m_reg_info.last_xmm = fpu_xmm15_x86_64; - m_reg_info.first_ymm = fpu_ymm0_x86_64; - m_reg_info.last_ymm = fpu_ymm15_x86_64; - m_reg_info.first_dr = dr0_x86_64; - m_reg_info.gpr_flags = gpr_rflags_x86_64; + m_reg_info.first_st = lldb_st0_x86_64; + m_reg_info.last_st = lldb_st7_x86_64; + m_reg_info.first_mm = lldb_mm0_x86_64; + m_reg_info.last_mm = lldb_mm7_x86_64; + m_reg_info.first_xmm = lldb_xmm0_x86_64; + m_reg_info.last_xmm = lldb_xmm15_x86_64; + m_reg_info.first_ymm = lldb_ymm0_x86_64; + m_reg_info.last_ymm = lldb_ymm15_x86_64; + m_reg_info.first_dr = lldb_dr0_x86_64; + m_reg_info.gpr_flags = lldb_rflags_x86_64; break; default: assert(false && "Unhandled target architecture."); diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h index 4db7802e1b44..0eec1d909c1a 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h @@ -11,285 +11,12 @@ #define liblldb_RegisterContextPOSIX_x86_H_ #include "lldb/Core/Log.h" +#include "lldb-x86-register-enums.h" #include "RegisterContextPOSIX.h" #include "RegisterContext_x86.h" class ProcessMonitor; -//--------------------------------------------------------------------------- -// Internal codes for all i386 registers. -//--------------------------------------------------------------------------- -enum -{ - k_first_gpr_i386, - gpr_eax_i386 = k_first_gpr_i386, - gpr_ebx_i386, - gpr_ecx_i386, - gpr_edx_i386, - gpr_edi_i386, - gpr_esi_i386, - gpr_ebp_i386, - gpr_esp_i386, - gpr_eip_i386, - gpr_eflags_i386, - gpr_cs_i386, - gpr_fs_i386, - gpr_gs_i386, - gpr_ss_i386, - gpr_ds_i386, - gpr_es_i386, - - k_first_alias_i386, - gpr_ax_i386 = k_first_alias_i386, - gpr_bx_i386, - gpr_cx_i386, - gpr_dx_i386, - gpr_di_i386, - gpr_si_i386, - gpr_bp_i386, - gpr_sp_i386, - gpr_ah_i386, - gpr_bh_i386, - gpr_ch_i386, - gpr_dh_i386, - gpr_al_i386, - gpr_bl_i386, - gpr_cl_i386, - gpr_dl_i386, - k_last_alias_i386 = gpr_dl_i386, - - k_last_gpr_i386 = k_last_alias_i386, - - k_first_fpr_i386, - fpu_fctrl_i386 = k_first_fpr_i386, - fpu_fstat_i386, - fpu_ftag_i386, - fpu_fop_i386, - fpu_fiseg_i386, - fpu_fioff_i386, - fpu_foseg_i386, - fpu_fooff_i386, - fpu_mxcsr_i386, - fpu_mxcsrmask_i386, - fpu_st0_i386, - fpu_st1_i386, - fpu_st2_i386, - fpu_st3_i386, - fpu_st4_i386, - fpu_st5_i386, - fpu_st6_i386, - fpu_st7_i386, - fpu_mm0_i386, - fpu_mm1_i386, - fpu_mm2_i386, - fpu_mm3_i386, - fpu_mm4_i386, - fpu_mm5_i386, - fpu_mm6_i386, - fpu_mm7_i386, - fpu_xmm0_i386, - fpu_xmm1_i386, - fpu_xmm2_i386, - fpu_xmm3_i386, - fpu_xmm4_i386, - fpu_xmm5_i386, - fpu_xmm6_i386, - fpu_xmm7_i386, - k_last_fpr_i386 = fpu_xmm7_i386, - - k_first_avx_i386, - fpu_ymm0_i386 = k_first_avx_i386, - fpu_ymm1_i386, - fpu_ymm2_i386, - fpu_ymm3_i386, - fpu_ymm4_i386, - fpu_ymm5_i386, - fpu_ymm6_i386, - fpu_ymm7_i386, - k_last_avx_i386 = fpu_ymm7_i386, - - dr0_i386, - dr1_i386, - dr2_i386, - dr3_i386, - dr4_i386, - dr5_i386, - dr6_i386, - dr7_i386, - - k_num_registers_i386, - k_num_gpr_registers_i386 = k_last_gpr_i386 - k_first_gpr_i386 + 1, - k_num_fpr_registers_i386 = k_last_fpr_i386 - k_first_fpr_i386 + 1, - k_num_avx_registers_i386 = k_last_avx_i386 - k_first_avx_i386 + 1 -}; - -//--------------------------------------------------------------------------- -// Internal codes for all x86_64 registers. -//--------------------------------------------------------------------------- -enum -{ - k_first_gpr_x86_64, - gpr_rax_x86_64 = k_first_gpr_x86_64, - gpr_rbx_x86_64, - gpr_rcx_x86_64, - gpr_rdx_x86_64, - gpr_rdi_x86_64, - gpr_rsi_x86_64, - gpr_rbp_x86_64, - gpr_rsp_x86_64, - gpr_r8_x86_64, - gpr_r9_x86_64, - gpr_r10_x86_64, - gpr_r11_x86_64, - gpr_r12_x86_64, - gpr_r13_x86_64, - gpr_r14_x86_64, - gpr_r15_x86_64, - gpr_rip_x86_64, - gpr_rflags_x86_64, - gpr_cs_x86_64, - gpr_fs_x86_64, - gpr_gs_x86_64, - gpr_ss_x86_64, - gpr_ds_x86_64, - gpr_es_x86_64, - - k_first_alias_x86_64, - gpr_eax_x86_64 = k_first_alias_x86_64, - gpr_ebx_x86_64, - gpr_ecx_x86_64, - gpr_edx_x86_64, - gpr_edi_x86_64, - gpr_esi_x86_64, - gpr_ebp_x86_64, - gpr_esp_x86_64, - gpr_r8d_x86_64, // Low 32 bits of r8 - gpr_r9d_x86_64, // Low 32 bits of r9 - gpr_r10d_x86_64, // Low 32 bits of r10 - gpr_r11d_x86_64, // Low 32 bits of r11 - gpr_r12d_x86_64, // Low 32 bits of r12 - gpr_r13d_x86_64, // Low 32 bits of r13 - gpr_r14d_x86_64, // Low 32 bits of r14 - gpr_r15d_x86_64, // Low 32 bits of r15 - gpr_ax_x86_64, - gpr_bx_x86_64, - gpr_cx_x86_64, - gpr_dx_x86_64, - gpr_di_x86_64, - gpr_si_x86_64, - gpr_bp_x86_64, - gpr_sp_x86_64, - gpr_r8w_x86_64, // Low 16 bits of r8 - gpr_r9w_x86_64, // Low 16 bits of r9 - gpr_r10w_x86_64, // Low 16 bits of r10 - gpr_r11w_x86_64, // Low 16 bits of r11 - gpr_r12w_x86_64, // Low 16 bits of r12 - gpr_r13w_x86_64, // Low 16 bits of r13 - gpr_r14w_x86_64, // Low 16 bits of r14 - gpr_r15w_x86_64, // Low 16 bits of r15 - gpr_ah_x86_64, - gpr_bh_x86_64, - gpr_ch_x86_64, - gpr_dh_x86_64, - gpr_al_x86_64, - gpr_bl_x86_64, - gpr_cl_x86_64, - gpr_dl_x86_64, - gpr_dil_x86_64, - gpr_sil_x86_64, - gpr_bpl_x86_64, - gpr_spl_x86_64, - gpr_r8l_x86_64, // Low 8 bits of r8 - gpr_r9l_x86_64, // Low 8 bits of r9 - gpr_r10l_x86_64, // Low 8 bits of r10 - gpr_r11l_x86_64, // Low 8 bits of r11 - gpr_r12l_x86_64, // Low 8 bits of r12 - gpr_r13l_x86_64, // Low 8 bits of r13 - gpr_r14l_x86_64, // Low 8 bits of r14 - gpr_r15l_x86_64, // Low 8 bits of r15 - k_last_alias_x86_64 = gpr_r15l_x86_64, - - k_last_gpr_x86_64 = k_last_alias_x86_64, - - k_first_fpr_x86_64, - fpu_fctrl_x86_64 = k_first_fpr_x86_64, - fpu_fstat_x86_64, - fpu_ftag_x86_64, - fpu_fop_x86_64, - fpu_fiseg_x86_64, - fpu_fioff_x86_64, - fpu_foseg_x86_64, - fpu_fooff_x86_64, - fpu_mxcsr_x86_64, - fpu_mxcsrmask_x86_64, - fpu_st0_x86_64, - fpu_st1_x86_64, - fpu_st2_x86_64, - fpu_st3_x86_64, - fpu_st4_x86_64, - fpu_st5_x86_64, - fpu_st6_x86_64, - fpu_st7_x86_64, - fpu_mm0_x86_64, - fpu_mm1_x86_64, - fpu_mm2_x86_64, - fpu_mm3_x86_64, - fpu_mm4_x86_64, - fpu_mm5_x86_64, - fpu_mm6_x86_64, - fpu_mm7_x86_64, - fpu_xmm0_x86_64, - fpu_xmm1_x86_64, - fpu_xmm2_x86_64, - fpu_xmm3_x86_64, - fpu_xmm4_x86_64, - fpu_xmm5_x86_64, - fpu_xmm6_x86_64, - fpu_xmm7_x86_64, - fpu_xmm8_x86_64, - fpu_xmm9_x86_64, - fpu_xmm10_x86_64, - fpu_xmm11_x86_64, - fpu_xmm12_x86_64, - fpu_xmm13_x86_64, - fpu_xmm14_x86_64, - fpu_xmm15_x86_64, - k_last_fpr_x86_64 = fpu_xmm15_x86_64, - - k_first_avx_x86_64, - fpu_ymm0_x86_64 = k_first_avx_x86_64, - fpu_ymm1_x86_64, - fpu_ymm2_x86_64, - fpu_ymm3_x86_64, - fpu_ymm4_x86_64, - fpu_ymm5_x86_64, - fpu_ymm6_x86_64, - fpu_ymm7_x86_64, - fpu_ymm8_x86_64, - fpu_ymm9_x86_64, - fpu_ymm10_x86_64, - fpu_ymm11_x86_64, - fpu_ymm12_x86_64, - fpu_ymm13_x86_64, - fpu_ymm14_x86_64, - fpu_ymm15_x86_64, - k_last_avx_x86_64 = fpu_ymm15_x86_64, - - dr0_x86_64, - dr1_x86_64, - dr2_x86_64, - dr3_x86_64, - dr4_x86_64, - dr5_x86_64, - dr6_x86_64, - dr7_x86_64, - - k_num_registers_x86_64, - k_num_gpr_registers_x86_64 = k_last_gpr_x86_64 - k_first_gpr_x86_64 + 1, - k_num_fpr_registers_x86_64 = k_last_fpr_x86_64 - k_first_fpr_x86_64 + 1, - k_num_avx_registers_x86_64 = k_last_avx_x86_64 - k_first_avx_x86_64 + 1 -}; - class RegisterContextPOSIX_x86 : public lldb_private::RegisterContext { @@ -422,7 +149,7 @@ protected: uint32_t gpr_flags; }; - uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64]; // 64-bit general purpose registers. + uint64_t m_gpr_x86_64[lldb_private::k_num_gpr_registers_x86_64]; // 64-bit general purpose registers. RegInfo m_reg_info; FPRType m_fpr_type; // determines the type of data stored by union FPR, if any. FPR m_fpr; // floating-point registers including extended register sets. diff --git a/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp b/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp index 46dafa11d8f7..200ef4d3d651 100644 --- a/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp +++ b/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp @@ -59,7 +59,7 @@ RegisterContextThreadMemory::UpdateRegisterContext () { OperatingSystem *os = process_sp->GetOperatingSystem (); if (os->IsOperatingSystemPluginThread (thread_sp)) - m_reg_ctx_sp = os->CreateRegisterContextForThread (thread_sp.get(), LLDB_INVALID_ADDRESS); + m_reg_ctx_sp = os->CreateRegisterContextForThread (thread_sp.get(), m_register_data_addr); } } } diff --git a/source/Plugins/Process/Utility/RegisterContext_powerpc.h b/source/Plugins/Process/Utility/RegisterContext_powerpc.h new file mode 100644 index 000000000000..cf54cc0c2145 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContext_powerpc.h @@ -0,0 +1,163 @@ +//===-- RegisterContext_powerpc.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContext_powerpc_H_ +#define liblldb_RegisterContext_powerpc_H_ + +// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF) +enum +{ + gcc_dwarf_r0_powerpc = 0, + gcc_dwarf_r1_powerpc, + gcc_dwarf_r2_powerpc, + gcc_dwarf_r3_powerpc, + gcc_dwarf_r4_powerpc, + gcc_dwarf_r5_powerpc, + gcc_dwarf_r6_powerpc, + gcc_dwarf_r7_powerpc, + gcc_dwarf_r8_powerpc, + gcc_dwarf_r9_powerpc, + gcc_dwarf_r10_powerpc, + gcc_dwarf_r11_powerpc, + gcc_dwarf_r12_powerpc, + gcc_dwarf_r13_powerpc, + gcc_dwarf_r14_powerpc, + gcc_dwarf_r15_powerpc, + gcc_dwarf_r16_powerpc, + gcc_dwarf_r17_powerpc, + gcc_dwarf_r18_powerpc, + gcc_dwarf_r19_powerpc, + gcc_dwarf_r20_powerpc, + gcc_dwarf_r21_powerpc, + gcc_dwarf_r22_powerpc, + gcc_dwarf_r23_powerpc, + gcc_dwarf_r24_powerpc, + gcc_dwarf_r25_powerpc, + gcc_dwarf_r26_powerpc, + gcc_dwarf_r27_powerpc, + gcc_dwarf_r28_powerpc, + gcc_dwarf_r29_powerpc, + gcc_dwarf_r30_powerpc, + gcc_dwarf_r31_powerpc, + gcc_dwarf_f0_powerpc, + gcc_dwarf_f1_powerpc, + gcc_dwarf_f2_powerpc, + gcc_dwarf_f3_powerpc, + gcc_dwarf_f4_powerpc, + gcc_dwarf_f5_powerpc, + gcc_dwarf_f6_powerpc, + gcc_dwarf_f7_powerpc, + gcc_dwarf_f8_powerpc, + gcc_dwarf_f9_powerpc, + gcc_dwarf_f10_powerpc, + gcc_dwarf_f11_powerpc, + gcc_dwarf_f12_powerpc, + gcc_dwarf_f13_powerpc, + gcc_dwarf_f14_powerpc, + gcc_dwarf_f15_powerpc, + gcc_dwarf_f16_powerpc, + gcc_dwarf_f17_powerpc, + gcc_dwarf_f18_powerpc, + gcc_dwarf_f19_powerpc, + gcc_dwarf_f20_powerpc, + gcc_dwarf_f21_powerpc, + gcc_dwarf_f22_powerpc, + gcc_dwarf_f23_powerpc, + gcc_dwarf_f24_powerpc, + gcc_dwarf_f25_powerpc, + gcc_dwarf_f26_powerpc, + gcc_dwarf_f27_powerpc, + gcc_dwarf_f28_powerpc, + gcc_dwarf_f29_powerpc, + gcc_dwarf_f30_powerpc, + gcc_dwarf_f31_powerpc, + gcc_dwarf_cr_powerpc, + gcc_dwarf_fpscr_powerpc, + gcc_dwarf_xer_powerpc = 101, + gcc_dwarf_lr_powerpc = 108, + gcc_dwarf_ctr_powerpc, + gcc_dwarf_pc_powerpc, +}; + +// GDB Register numbers (eRegisterKindGDB) +enum +{ + gdb_r0_powerpc = 0, + gdb_r1_powerpc, + gdb_r2_powerpc, + gdb_r3_powerpc, + gdb_r4_powerpc, + gdb_r5_powerpc, + gdb_r6_powerpc, + gdb_r7_powerpc, + gdb_r8_powerpc, + gdb_r9_powerpc, + gdb_r10_powerpc, + gdb_r11_powerpc, + gdb_r12_powerpc, + gdb_r13_powerpc, + gdb_r14_powerpc, + gdb_r15_powerpc, + gdb_r16_powerpc, + gdb_r17_powerpc, + gdb_r18_powerpc, + gdb_r19_powerpc, + gdb_r20_powerpc, + gdb_r21_powerpc, + gdb_r22_powerpc, + gdb_r23_powerpc, + gdb_r24_powerpc, + gdb_r25_powerpc, + gdb_r26_powerpc, + gdb_r27_powerpc, + gdb_r28_powerpc, + gdb_r29_powerpc, + gdb_r30_powerpc, + gdb_r31_powerpc, + gdb_f0_powerpc, + gdb_f1_powerpc, + gdb_f2_powerpc, + gdb_f3_powerpc, + gdb_f4_powerpc, + gdb_f5_powerpc, + gdb_f6_powerpc, + gdb_f7_powerpc, + gdb_f8_powerpc, + gdb_f9_powerpc, + gdb_f10_powerpc, + gdb_f11_powerpc, + gdb_f12_powerpc, + gdb_f13_powerpc, + gdb_f14_powerpc, + gdb_f15_powerpc, + gdb_f16_powerpc, + gdb_f17_powerpc, + gdb_f18_powerpc, + gdb_f19_powerpc, + gdb_f20_powerpc, + gdb_f21_powerpc, + gdb_f22_powerpc, + gdb_f23_powerpc, + gdb_f24_powerpc, + gdb_f25_powerpc, + gdb_f26_powerpc, + gdb_f27_powerpc, + gdb_f28_powerpc, + gdb_f29_powerpc, + gdb_f30_powerpc, + gdb_f31_powerpc, + gdb_cr_powerpc, + gdb_fpscr_powerpc, + gdb_xer_powerpc = 101, + gdb_lr_powerpc = 108, + gdb_ctr_powerpc, + gdb_pc_powerpc, +}; + +#endif // liblldb_RegisterContext_powerpc_H_ diff --git a/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/source/Plugins/Process/Utility/RegisterInfos_arm64.h index 1bb4e89c8f78..b687423622a4 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_arm64.h +++ b/source/Plugins/Process/Utility/RegisterInfos_arm64.h @@ -15,8 +15,8 @@ #include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" -#include "ARM64_GCC_Registers.h" -#include "ARM64_DWARF_Registers.h" +#include "Utility/ARM64_GCC_Registers.h" +#include "Utility/ARM64_DWARF_Registers.h" #ifndef GPR_OFFSET #error GPR_OFFSET must be defined before including this header file diff --git a/source/Plugins/Process/Utility/RegisterInfos_i386.h b/source/Plugins/Process/Utility/RegisterInfos_i386.h index fa152b4147ce..fc94b8b2a738 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_i386.h +++ b/source/Plugins/Process/Utility/RegisterInfos_i386.h @@ -42,37 +42,37 @@ // Note that the size and offset will be updated by platform-specific classes. #define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, sizeof(((GPR*)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_i386 }, NULL, NULL } + eFormatHex, { kind1, kind2, kind3, kind4, lldb_##reg##_i386 }, NULL, NULL } #define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \ { #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, fpu_##name##_i386 }, NULL, NULL } + eFormatHex, { kind1, kind2, kind3, kind4, lldb_##name##_i386 }, NULL, NULL } // RegisterKind: GCC, DWARF, Generic, GDB, LLDB #define DEFINE_FP_ST(reg, i) \ { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \ eEncodingVector, eFormatVectorOfUInt8, \ - { gcc_st##i##_i386, dwarf_st##i##_i386, LLDB_INVALID_REGNUM, gdb_st##i##_i386, fpu_st##i##_i386 }, \ + { gcc_st##i##_i386, dwarf_st##i##_i386, LLDB_INVALID_REGNUM, gdb_st##i##_i386, lldb_st##i##_i386 }, \ NULL, NULL } #define DEFINE_FP_MM(reg, i) \ { #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]), \ eEncodingUint, eFormatHex, \ - { gcc_mm##i##_i386, dwarf_mm##i##_i386, LLDB_INVALID_REGNUM, gdb_mm##i##_i386, fpu_mm##i##_i386 }, \ + { gcc_mm##i##_i386, dwarf_mm##i##_i386, LLDB_INVALID_REGNUM, gdb_mm##i##_i386, lldb_mm##i##_i386 }, \ NULL, NULL } #define DEFINE_XMM(reg, i) \ { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \ eEncodingVector, eFormatVectorOfUInt8, \ - { gcc_##reg##i##_i386, dwarf_##reg##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##_i386, fpu_##reg##i##_i386}, \ + { gcc_##reg##i##_i386, dwarf_##reg##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##_i386, lldb_##reg##i##_i386}, \ NULL, NULL } // I believe the YMM registers use dwarf_xmm_%_i386 register numbers and then differentiate based on register size. #define DEFINE_YMM(reg, i) \ { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(reg[i]), \ eEncodingVector, eFormatVectorOfUInt8, \ - { LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##h_i386, fpu_##reg##i##_i386 }, \ + { LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##h_i386, lldb_##reg##i##_i386 }, \ NULL, NULL } #define DEFINE_DR(reg, i) \ @@ -82,13 +82,13 @@ #define DEFINE_GPR_PSEUDO_16(reg16, reg32) \ { #reg16, NULL, 2, GPR_OFFSET(reg32), eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg16##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 } + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg16##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 } #define DEFINE_GPR_PSEUDO_8H(reg8, reg32) \ { #reg8, NULL, 1, GPR_OFFSET(reg32)+1, eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 } + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg8##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 } #define DEFINE_GPR_PSEUDO_8L(reg8, reg32) \ { #reg8, NULL, 1, GPR_OFFSET(reg32), eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 } + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg8##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 } static RegisterInfo g_register_infos_i386[] = diff --git a/source/Plugins/Process/Utility/RegisterInfos_powerpc.h b/source/Plugins/Process/Utility/RegisterInfos_powerpc.h new file mode 100644 index 000000000000..045426648105 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterInfos_powerpc.h @@ -0,0 +1,144 @@ +//===-- RegisterInfos_powerpc.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#include + +// 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 GPR_SIZE(regname) \ + (sizeof(((GPR*)NULL)->regname)) + +#ifdef DECLARE_REGISTER_INFOS_POWERPC_STRUCT + +// Note that the size and offset will be updated by platform-specific classes. +#define DEFINE_GPR(reg, alt, lldb_kind) \ + { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, gpr_##reg##_powerpc }, NULL, NULL } +#define DEFINE_FPR(reg, lldb_kind) \ + { #reg, NULL, 8, FPR_OFFSET(reg), eEncodingIEEE754, \ + eFormatFloat, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, fpr_##reg##_powerpc }, NULL, NULL } + + // General purpose registers. GCC, DWARF, Generic, GDB +#define POWERPC_REGS \ + DEFINE_GPR(r0, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r1, "sp", LLDB_REGNUM_GENERIC_SP), \ + DEFINE_GPR(r2, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r3, "arg1",LLDB_REGNUM_GENERIC_ARG1), \ + DEFINE_GPR(r4, "arg2",LLDB_REGNUM_GENERIC_ARG2), \ + DEFINE_GPR(r5, "arg3",LLDB_REGNUM_GENERIC_ARG3), \ + DEFINE_GPR(r6, "arg4",LLDB_REGNUM_GENERIC_ARG4), \ + DEFINE_GPR(r7, "arg5",LLDB_REGNUM_GENERIC_ARG5), \ + DEFINE_GPR(r8, "arg6",LLDB_REGNUM_GENERIC_ARG6), \ + DEFINE_GPR(r9, "arg7",LLDB_REGNUM_GENERIC_ARG7), \ + DEFINE_GPR(r10, "arg8",LLDB_REGNUM_GENERIC_ARG8), \ + DEFINE_GPR(r11, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r12, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r13, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r14, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r15, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r16, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r17, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r18, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r19, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r20, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r21, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r22, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r23, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r24, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r25, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r26, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r27, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r28, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r29, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r30, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r31, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(lr, "lr", LLDB_REGNUM_GENERIC_RA), \ + DEFINE_GPR(cr, "cr", LLDB_REGNUM_GENERIC_FLAGS), \ + DEFINE_GPR(xer, "xer", LLDB_INVALID_REGNUM), \ + DEFINE_GPR(ctr, "ctr", LLDB_INVALID_REGNUM), \ + DEFINE_GPR(pc, "pc", LLDB_REGNUM_GENERIC_PC), \ + DEFINE_FPR(f0, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f1, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f2, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f3, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f4, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f5, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f6, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f7, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f8, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f9, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f10, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f11, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f12, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f13, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f14, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f15, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f16, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f17, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f18, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f19, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f20, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f21, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f22, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f23, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f24, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f25, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f26, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f27, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f28, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f29, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f30, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f31, LLDB_INVALID_REGNUM), \ + { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { gcc_dwarf_fpscr_powerpc, gcc_dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, gdb_fpscr_powerpc, fpr_fpscr_powerpc }, NULL, NULL }, +static RegisterInfo +g_register_infos_powerpc64[] = +{ +#define GPR GPR64 + POWERPC_REGS +#undef GPR +}; + +static RegisterInfo +g_register_infos_powerpc32[] = +{ +#define GPR GPR32 + POWERPC_REGS +#undef GPR +}; + +static RegisterInfo +g_register_infos_powerpc64_32[] = +{ +#define GPR GPR64 +#undef GPR_SIZE +#define GPR_SIZE(reg) (sizeof(uint32_t)) +#undef GPR_OFFSET +#define GPR_OFFSET(regname) \ + (offsetof(GPR, regname) + (sizeof(((GPR *)NULL)->regname) - GPR_SIZE(reg))) + POWERPC_REGS +#undef GPR +}; + +static_assert((sizeof(g_register_infos_powerpc32) / sizeof(g_register_infos_powerpc32[0])) == k_num_registers_powerpc, + "g_register_infos_powerpc32 has wrong number of register infos"); +static_assert((sizeof(g_register_infos_powerpc64) / sizeof(g_register_infos_powerpc64[0])) == k_num_registers_powerpc, + "g_register_infos_powerpc64 has wrong number of register infos"); +static_assert(sizeof(g_register_infos_powerpc64_32) == sizeof(g_register_infos_powerpc64), + "g_register_infos_powerpc64_32 doesn't match size of g_register_infos_powerpc64"); + +#undef DEFINE_FPR +#undef DEFINE_GPR + +#endif // DECLARE_REGISTER_INFOS_POWERPC_STRUCT + +#undef GPR_OFFSET + diff --git a/source/Plugins/Process/Utility/RegisterInfos_x86_64.h b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h index c4dc6041ce43..c1bcd27053c6 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_x86_64.h +++ b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h @@ -42,34 +42,34 @@ // Note that the size and offset will be updated by platform-specific classes. #define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, sizeof(((GPR*)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_x86_64 }, NULL, NULL } + eFormatHex, { kind1, kind2, kind3, kind4, lldb_##reg##_x86_64 }, NULL, NULL } #define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \ { #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, fpu_##name##_x86_64 }, NULL, NULL } + eFormatHex, { kind1, kind2, kind3, kind4, lldb_##name##_x86_64 }, NULL, NULL } #define DEFINE_FP_ST(reg, i) \ { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \ eEncodingVector, eFormatVectorOfUInt8, \ - { gcc_dwarf_st##i##_x86_64, gcc_dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, fpu_st##i##_x86_64 }, \ + { gcc_dwarf_st##i##_x86_64, gcc_dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, lldb_st##i##_x86_64 }, \ NULL, NULL } #define DEFINE_FP_MM(reg, i) \ { #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]), \ eEncodingUint, eFormatHex, \ - { gcc_dwarf_mm##i##_x86_64, gcc_dwarf_mm##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, fpu_mm##i##_x86_64 }, \ + { gcc_dwarf_mm##i##_x86_64, gcc_dwarf_mm##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, lldb_mm##i##_x86_64 }, \ NULL, NULL } #define DEFINE_XMM(reg, i) \ { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \ eEncodingVector, eFormatVectorOfUInt8, \ - { gcc_dwarf_##reg##i##_x86_64, gcc_dwarf_##reg##i##_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##_x86_64, fpu_##reg##i##_x86_64}, \ + { gcc_dwarf_##reg##i##_x86_64, gcc_dwarf_##reg##i##_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##_x86_64, lldb_##reg##i##_x86_64}, \ NULL, NULL } #define DEFINE_YMM(reg, i) \ { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(reg[i]), \ eEncodingVector, eFormatVectorOfUInt8, \ - { gcc_dwarf_##reg##i##h_x86_64, gcc_dwarf_##reg##i##h_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##h_x86_64, fpu_##reg##i##_x86_64 }, \ + { gcc_dwarf_##reg##i##h_x86_64, gcc_dwarf_##reg##i##h_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##h_x86_64, lldb_##reg##i##_x86_64 }, \ NULL, NULL } #define DEFINE_DR(reg, i) \ @@ -79,16 +79,16 @@ #define DEFINE_GPR_PSEUDO_32(reg32, reg64) \ { #reg32, NULL, 4, GPR_OFFSET(reg64), eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg32##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg32##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } #define DEFINE_GPR_PSEUDO_16(reg16, reg64) \ { #reg16, NULL, 2, GPR_OFFSET(reg64), eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg16##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg16##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } #define DEFINE_GPR_PSEUDO_8H(reg8, reg64) \ { #reg8, NULL, 1, GPR_OFFSET(reg64)+1, eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } #define DEFINE_GPR_PSEUDO_8L(reg8, reg64) \ { #reg8, NULL, 1, GPR_OFFSET(reg64), eEncodingUint, \ - eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } static RegisterInfo g_register_infos_x86_64[] = @@ -273,37 +273,37 @@ static_assert((sizeof(g_register_infos_x86_64) / sizeof(g_register_infos_x86_64[ #define UPDATE_GPR_INFO(reg, reg64) \ do { \ - g_register_infos[gpr_##reg##_i386].byte_offset = GPR_OFFSET(reg64); \ + g_register_infos[lldb_##reg##_i386].byte_offset = GPR_OFFSET(reg64); \ } while(false); #define UPDATE_GPR_INFO_8H(reg, reg64) \ do { \ - g_register_infos[gpr_##reg##_i386].byte_offset = GPR_OFFSET(reg64) + 1; \ + g_register_infos[lldb_##reg##_i386].byte_offset = GPR_OFFSET(reg64) + 1; \ } while(false); #define UPDATE_FPR_INFO(reg, reg64) \ do { \ - g_register_infos[fpu_##reg##_i386].byte_offset = FPR_OFFSET(reg64); \ + g_register_infos[lldb_##reg##_i386].byte_offset = FPR_OFFSET(reg64); \ } while(false); #define UPDATE_FP_INFO(reg, i) \ do { \ - g_register_infos[fpu_##reg##i##_i386].byte_offset = FPR_OFFSET(stmm[i]); \ + g_register_infos[lldb_##reg##i##_i386].byte_offset = FPR_OFFSET(stmm[i]); \ } while(false); #define UPDATE_XMM_INFO(reg, i) \ do { \ - g_register_infos[fpu_##reg##i##_i386].byte_offset = FPR_OFFSET(reg[i]); \ + g_register_infos[lldb_##reg##i##_i386].byte_offset = FPR_OFFSET(reg[i]); \ } while(false); #define UPDATE_YMM_INFO(reg, i) \ do { \ - g_register_infos[fpu_##reg##i##_i386].byte_offset = YMM_OFFSET(reg[i]); \ + g_register_infos[lldb_##reg##i##_i386].byte_offset = YMM_OFFSET(reg[i]); \ } while(false); #define UPDATE_DR_INFO(reg_index) \ do { \ - g_register_infos[dr##reg_index##_i386].byte_offset = DR_OFFSET(reg_index); \ + g_register_infos[lldb_dr##reg_index##_i386].byte_offset = DR_OFFSET(reg_index); \ } while(false); // Update the register offsets diff --git a/source/Plugins/Process/Utility/StopInfoMachException.cpp b/source/Plugins/Process/Utility/StopInfoMachException.cpp index 0e3e559aef5c..a69b38b6c93e 100644 --- a/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -423,9 +423,11 @@ StopInfoMachException::CreateStopReasonWithMachException wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID()); } - // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as EXC_BAD_ACCESS - if (thread.GetTemporaryResumeState() == eStateStepping) - return StopInfo::CreateStopReasonToTrace(thread); + else + { + is_actual_breakpoint = true; + is_trace_if_actual_breakpoint_missing = true; + } } else if (exc_code == 1) // EXC_ARM_BREAKPOINT { diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp index 37fd4f489552..fc592e60d86d 100644 --- a/source/Plugins/Process/Utility/UnwindLLDB.cpp +++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp @@ -172,8 +172,9 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi) if (!reg_ctx_sp->IsValid()) { - // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return - // true. Subsequent calls to TryFallbackUnwindPlan() will return false. + // We failed to get a valid RegisterContext. + // See if the regctx below this on the stack has a fallback unwind plan it can use. + // Subsequent calls to TryFallbackUnwindPlan() will return false. if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) { return AddOneMoreFrame (abi); @@ -207,18 +208,35 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi) // these. if (reg_ctx_sp->IsTrapHandlerFrame() == false) { - // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return - // true. Subsequent calls to TryFallbackUnwindPlan() will return false. - if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) + // See if we can find a fallback unwind plan for THIS frame. It may be + // that the UnwindPlan we're using for THIS frame was bad and gave us a + // bad CFA. + // If that's not it, then see if we can change the UnwindPlan for the frame + // below us ("NEXT") -- see if using that other UnwindPlan gets us a better + // unwind state. + if (reg_ctx_sp->TryFallbackUnwindPlan() == false + || reg_ctx_sp->GetCFA (cursor_sp->cfa) == false + || abi->CallFrameAddressIsValid(cursor_sp->cfa) == false) { - return AddOneMoreFrame (abi); + if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) + { + return AddOneMoreFrame (abi); + } + if (log) + { + log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); + } + goto unwind_done; } - if (log) + else { - log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + if (log) + { + log->Printf("%*sFrame %d had a bad CFA value but we switched the UnwindPlan being used and got one that looks more realistic.", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); + } } - goto unwind_done; } } if (!reg_ctx_sp->ReadPC (cursor_sp->start_pc)) @@ -366,6 +384,14 @@ UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_privat UnwindLLDB::RegisterSearchResult result; result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc); + // We descended down to the live register context aka stack frame 0 and are reading the value + // out of a live register. + if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound + && regloc.type == UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext) + { + return true; + } + // If we have unwind instructions saying that register N is saved in register M in the middle of // the stack (and N can equal M here, meaning the register was not used in this function), then // change the register number we're looking for to M and keep looking for a concrete location diff --git a/source/Plugins/Process/Utility/UnwindLLDB.h b/source/Plugins/Process/Utility/UnwindLLDB.h index eb5400389df3..35d85e2e3d26 100644 --- a/source/Plugins/Process/Utility/UnwindLLDB.h +++ b/source/Plugins/Process/Utility/UnwindLLDB.h @@ -48,7 +48,8 @@ protected: eRegisterSavedAtMemoryLocation, // register is saved at a specific word of target mem (target_memory_location) eRegisterInRegister, // register is available in a (possible other) register (register_number) eRegisterSavedAtHostMemoryLocation, // register is saved at a word in lldb's address space - eRegisterValueInferred // register val was computed (and is in inferred_value) + eRegisterValueInferred, // register val was computed (and is in inferred_value) + eRegisterInLiveRegisterContext // register value is in a live (stack frame #0) register }; int type; union diff --git a/source/Plugins/Process/Utility/lldb-x86-register-enums.h b/source/Plugins/Process/Utility/lldb-x86-register-enums.h index c4706d567b70..99fca3005820 100644 --- a/source/Plugins/Process/Utility/lldb-x86-register-enums.h +++ b/source/Plugins/Process/Utility/lldb-x86-register-enums.h @@ -12,6 +12,7 @@ namespace lldb_private { + // LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) //--------------------------------------------------------------------------- // Internal codes for all i386 registers. @@ -19,100 +20,100 @@ namespace lldb_private enum { k_first_gpr_i386, - gpr_eax_i386 = k_first_gpr_i386, - gpr_ebx_i386, - gpr_ecx_i386, - gpr_edx_i386, - gpr_edi_i386, - gpr_esi_i386, - gpr_ebp_i386, - gpr_esp_i386, - gpr_eip_i386, - gpr_eflags_i386, - gpr_cs_i386, - gpr_fs_i386, - gpr_gs_i386, - gpr_ss_i386, - gpr_ds_i386, - gpr_es_i386, + lldb_eax_i386 = k_first_gpr_i386, + lldb_ebx_i386, + lldb_ecx_i386, + lldb_edx_i386, + lldb_edi_i386, + lldb_esi_i386, + lldb_ebp_i386, + lldb_esp_i386, + lldb_eip_i386, + lldb_eflags_i386, + lldb_cs_i386, + lldb_fs_i386, + lldb_gs_i386, + lldb_ss_i386, + lldb_ds_i386, + lldb_es_i386, k_first_alias_i386, - gpr_ax_i386 = k_first_alias_i386, - gpr_bx_i386, - gpr_cx_i386, - gpr_dx_i386, - gpr_di_i386, - gpr_si_i386, - gpr_bp_i386, - gpr_sp_i386, - gpr_ah_i386, - gpr_bh_i386, - gpr_ch_i386, - gpr_dh_i386, - gpr_al_i386, - gpr_bl_i386, - gpr_cl_i386, - gpr_dl_i386, - k_last_alias_i386 = gpr_dl_i386, + lldb_ax_i386 = k_first_alias_i386, + lldb_bx_i386, + lldb_cx_i386, + lldb_dx_i386, + lldb_di_i386, + lldb_si_i386, + lldb_bp_i386, + lldb_sp_i386, + lldb_ah_i386, + lldb_bh_i386, + lldb_ch_i386, + lldb_dh_i386, + lldb_al_i386, + lldb_bl_i386, + lldb_cl_i386, + lldb_dl_i386, + k_last_alias_i386 = lldb_dl_i386, k_last_gpr_i386 = k_last_alias_i386, k_first_fpr_i386, - fpu_fctrl_i386 = k_first_fpr_i386, - fpu_fstat_i386, - fpu_ftag_i386, - fpu_fop_i386, - fpu_fiseg_i386, - fpu_fioff_i386, - fpu_foseg_i386, - fpu_fooff_i386, - fpu_mxcsr_i386, - fpu_mxcsrmask_i386, - fpu_st0_i386, - fpu_st1_i386, - fpu_st2_i386, - fpu_st3_i386, - fpu_st4_i386, - fpu_st5_i386, - fpu_st6_i386, - fpu_st7_i386, - fpu_mm0_i386, - fpu_mm1_i386, - fpu_mm2_i386, - fpu_mm3_i386, - fpu_mm4_i386, - fpu_mm5_i386, - fpu_mm6_i386, - fpu_mm7_i386, - fpu_xmm0_i386, - fpu_xmm1_i386, - fpu_xmm2_i386, - fpu_xmm3_i386, - fpu_xmm4_i386, - fpu_xmm5_i386, - fpu_xmm6_i386, - fpu_xmm7_i386, - k_last_fpr_i386 = fpu_xmm7_i386, + lldb_fctrl_i386 = k_first_fpr_i386, + lldb_fstat_i386, + lldb_ftag_i386, + lldb_fop_i386, + lldb_fiseg_i386, + lldb_fioff_i386, + lldb_foseg_i386, + lldb_fooff_i386, + lldb_mxcsr_i386, + lldb_mxcsrmask_i386, + lldb_st0_i386, + lldb_st1_i386, + lldb_st2_i386, + lldb_st3_i386, + lldb_st4_i386, + lldb_st5_i386, + lldb_st6_i386, + lldb_st7_i386, + lldb_mm0_i386, + lldb_mm1_i386, + lldb_mm2_i386, + lldb_mm3_i386, + lldb_mm4_i386, + lldb_mm5_i386, + lldb_mm6_i386, + lldb_mm7_i386, + lldb_xmm0_i386, + lldb_xmm1_i386, + lldb_xmm2_i386, + lldb_xmm3_i386, + lldb_xmm4_i386, + lldb_xmm5_i386, + lldb_xmm6_i386, + lldb_xmm7_i386, + k_last_fpr_i386 = lldb_xmm7_i386, k_first_avx_i386, - fpu_ymm0_i386 = k_first_avx_i386, - fpu_ymm1_i386, - fpu_ymm2_i386, - fpu_ymm3_i386, - fpu_ymm4_i386, - fpu_ymm5_i386, - fpu_ymm6_i386, - fpu_ymm7_i386, - k_last_avx_i386 = fpu_ymm7_i386, + lldb_ymm0_i386 = k_first_avx_i386, + lldb_ymm1_i386, + lldb_ymm2_i386, + lldb_ymm3_i386, + lldb_ymm4_i386, + lldb_ymm5_i386, + lldb_ymm6_i386, + lldb_ymm7_i386, + k_last_avx_i386 = lldb_ymm7_i386, - dr0_i386, - dr1_i386, - dr2_i386, - dr3_i386, - dr4_i386, - dr5_i386, - dr6_i386, - dr7_i386, + lldb_dr0_i386, + lldb_dr1_i386, + lldb_dr2_i386, + lldb_dr3_i386, + lldb_dr4_i386, + lldb_dr5_i386, + lldb_dr6_i386, + lldb_dr7_i386, k_num_registers_i386, k_num_gpr_registers_i386 = k_last_gpr_i386 - k_first_gpr_i386 + 1, @@ -126,160 +127,160 @@ namespace lldb_private enum { k_first_gpr_x86_64, - gpr_rax_x86_64 = k_first_gpr_x86_64, - gpr_rbx_x86_64, - gpr_rcx_x86_64, - gpr_rdx_x86_64, - gpr_rdi_x86_64, - gpr_rsi_x86_64, - gpr_rbp_x86_64, - gpr_rsp_x86_64, - gpr_r8_x86_64, - gpr_r9_x86_64, - gpr_r10_x86_64, - gpr_r11_x86_64, - gpr_r12_x86_64, - gpr_r13_x86_64, - gpr_r14_x86_64, - gpr_r15_x86_64, - gpr_rip_x86_64, - gpr_rflags_x86_64, - gpr_cs_x86_64, - gpr_fs_x86_64, - gpr_gs_x86_64, - gpr_ss_x86_64, - gpr_ds_x86_64, - gpr_es_x86_64, + lldb_rax_x86_64 = k_first_gpr_x86_64, + lldb_rbx_x86_64, + lldb_rcx_x86_64, + lldb_rdx_x86_64, + lldb_rdi_x86_64, + lldb_rsi_x86_64, + lldb_rbp_x86_64, + lldb_rsp_x86_64, + lldb_r8_x86_64, + lldb_r9_x86_64, + lldb_r10_x86_64, + lldb_r11_x86_64, + lldb_r12_x86_64, + lldb_r13_x86_64, + lldb_r14_x86_64, + lldb_r15_x86_64, + lldb_rip_x86_64, + lldb_rflags_x86_64, + lldb_cs_x86_64, + lldb_fs_x86_64, + lldb_gs_x86_64, + lldb_ss_x86_64, + lldb_ds_x86_64, + lldb_es_x86_64, k_first_alias_x86_64, - gpr_eax_x86_64 = k_first_alias_x86_64, - gpr_ebx_x86_64, - gpr_ecx_x86_64, - gpr_edx_x86_64, - gpr_edi_x86_64, - gpr_esi_x86_64, - gpr_ebp_x86_64, - gpr_esp_x86_64, - gpr_r8d_x86_64, // Low 32 bits of r8 - gpr_r9d_x86_64, // Low 32 bits of r9 - gpr_r10d_x86_64, // Low 32 bits of r10 - gpr_r11d_x86_64, // Low 32 bits of r11 - gpr_r12d_x86_64, // Low 32 bits of r12 - gpr_r13d_x86_64, // Low 32 bits of r13 - gpr_r14d_x86_64, // Low 32 bits of r14 - gpr_r15d_x86_64, // Low 32 bits of r15 - gpr_ax_x86_64, - gpr_bx_x86_64, - gpr_cx_x86_64, - gpr_dx_x86_64, - gpr_di_x86_64, - gpr_si_x86_64, - gpr_bp_x86_64, - gpr_sp_x86_64, - gpr_r8w_x86_64, // Low 16 bits of r8 - gpr_r9w_x86_64, // Low 16 bits of r9 - gpr_r10w_x86_64, // Low 16 bits of r10 - gpr_r11w_x86_64, // Low 16 bits of r11 - gpr_r12w_x86_64, // Low 16 bits of r12 - gpr_r13w_x86_64, // Low 16 bits of r13 - gpr_r14w_x86_64, // Low 16 bits of r14 - gpr_r15w_x86_64, // Low 16 bits of r15 - gpr_ah_x86_64, - gpr_bh_x86_64, - gpr_ch_x86_64, - gpr_dh_x86_64, - gpr_al_x86_64, - gpr_bl_x86_64, - gpr_cl_x86_64, - gpr_dl_x86_64, - gpr_dil_x86_64, - gpr_sil_x86_64, - gpr_bpl_x86_64, - gpr_spl_x86_64, - gpr_r8l_x86_64, // Low 8 bits of r8 - gpr_r9l_x86_64, // Low 8 bits of r9 - gpr_r10l_x86_64, // Low 8 bits of r10 - gpr_r11l_x86_64, // Low 8 bits of r11 - gpr_r12l_x86_64, // Low 8 bits of r12 - gpr_r13l_x86_64, // Low 8 bits of r13 - gpr_r14l_x86_64, // Low 8 bits of r14 - gpr_r15l_x86_64, // Low 8 bits of r15 - k_last_alias_x86_64 = gpr_r15l_x86_64, + lldb_eax_x86_64 = k_first_alias_x86_64, + lldb_ebx_x86_64, + lldb_ecx_x86_64, + lldb_edx_x86_64, + lldb_edi_x86_64, + lldb_esi_x86_64, + lldb_ebp_x86_64, + lldb_esp_x86_64, + lldb_r8d_x86_64, // Low 32 bits of r8 + lldb_r9d_x86_64, // Low 32 bits of r9 + lldb_r10d_x86_64, // Low 32 bits of r10 + lldb_r11d_x86_64, // Low 32 bits of r11 + lldb_r12d_x86_64, // Low 32 bits of r12 + lldb_r13d_x86_64, // Low 32 bits of r13 + lldb_r14d_x86_64, // Low 32 bits of r14 + lldb_r15d_x86_64, // Low 32 bits of r15 + lldb_ax_x86_64, + lldb_bx_x86_64, + lldb_cx_x86_64, + lldb_dx_x86_64, + lldb_di_x86_64, + lldb_si_x86_64, + lldb_bp_x86_64, + lldb_sp_x86_64, + lldb_r8w_x86_64, // Low 16 bits of r8 + lldb_r9w_x86_64, // Low 16 bits of r9 + lldb_r10w_x86_64, // Low 16 bits of r10 + lldb_r11w_x86_64, // Low 16 bits of r11 + lldb_r12w_x86_64, // Low 16 bits of r12 + lldb_r13w_x86_64, // Low 16 bits of r13 + lldb_r14w_x86_64, // Low 16 bits of r14 + lldb_r15w_x86_64, // Low 16 bits of r15 + lldb_ah_x86_64, + lldb_bh_x86_64, + lldb_ch_x86_64, + lldb_dh_x86_64, + lldb_al_x86_64, + lldb_bl_x86_64, + lldb_cl_x86_64, + lldb_dl_x86_64, + lldb_dil_x86_64, + lldb_sil_x86_64, + lldb_bpl_x86_64, + lldb_spl_x86_64, + lldb_r8l_x86_64, // Low 8 bits of r8 + lldb_r9l_x86_64, // Low 8 bits of r9 + lldb_r10l_x86_64, // Low 8 bits of r10 + lldb_r11l_x86_64, // Low 8 bits of r11 + lldb_r12l_x86_64, // Low 8 bits of r12 + lldb_r13l_x86_64, // Low 8 bits of r13 + lldb_r14l_x86_64, // Low 8 bits of r14 + lldb_r15l_x86_64, // Low 8 bits of r15 + k_last_alias_x86_64 = lldb_r15l_x86_64, k_last_gpr_x86_64 = k_last_alias_x86_64, k_first_fpr_x86_64, - fpu_fctrl_x86_64 = k_first_fpr_x86_64, - fpu_fstat_x86_64, - fpu_ftag_x86_64, - fpu_fop_x86_64, - fpu_fiseg_x86_64, - fpu_fioff_x86_64, - fpu_foseg_x86_64, - fpu_fooff_x86_64, - fpu_mxcsr_x86_64, - fpu_mxcsrmask_x86_64, - fpu_st0_x86_64, - fpu_st1_x86_64, - fpu_st2_x86_64, - fpu_st3_x86_64, - fpu_st4_x86_64, - fpu_st5_x86_64, - fpu_st6_x86_64, - fpu_st7_x86_64, - fpu_mm0_x86_64, - fpu_mm1_x86_64, - fpu_mm2_x86_64, - fpu_mm3_x86_64, - fpu_mm4_x86_64, - fpu_mm5_x86_64, - fpu_mm6_x86_64, - fpu_mm7_x86_64, - fpu_xmm0_x86_64, - fpu_xmm1_x86_64, - fpu_xmm2_x86_64, - fpu_xmm3_x86_64, - fpu_xmm4_x86_64, - fpu_xmm5_x86_64, - fpu_xmm6_x86_64, - fpu_xmm7_x86_64, - fpu_xmm8_x86_64, - fpu_xmm9_x86_64, - fpu_xmm10_x86_64, - fpu_xmm11_x86_64, - fpu_xmm12_x86_64, - fpu_xmm13_x86_64, - fpu_xmm14_x86_64, - fpu_xmm15_x86_64, - k_last_fpr_x86_64 = fpu_xmm15_x86_64, + lldb_fctrl_x86_64 = k_first_fpr_x86_64, + lldb_fstat_x86_64, + lldb_ftag_x86_64, + lldb_fop_x86_64, + lldb_fiseg_x86_64, + lldb_fioff_x86_64, + lldb_foseg_x86_64, + lldb_fooff_x86_64, + lldb_mxcsr_x86_64, + lldb_mxcsrmask_x86_64, + lldb_st0_x86_64, + lldb_st1_x86_64, + lldb_st2_x86_64, + lldb_st3_x86_64, + lldb_st4_x86_64, + lldb_st5_x86_64, + lldb_st6_x86_64, + lldb_st7_x86_64, + lldb_mm0_x86_64, + lldb_mm1_x86_64, + lldb_mm2_x86_64, + lldb_mm3_x86_64, + lldb_mm4_x86_64, + lldb_mm5_x86_64, + lldb_mm6_x86_64, + lldb_mm7_x86_64, + lldb_xmm0_x86_64, + lldb_xmm1_x86_64, + lldb_xmm2_x86_64, + lldb_xmm3_x86_64, + lldb_xmm4_x86_64, + lldb_xmm5_x86_64, + lldb_xmm6_x86_64, + lldb_xmm7_x86_64, + lldb_xmm8_x86_64, + lldb_xmm9_x86_64, + lldb_xmm10_x86_64, + lldb_xmm11_x86_64, + lldb_xmm12_x86_64, + lldb_xmm13_x86_64, + lldb_xmm14_x86_64, + lldb_xmm15_x86_64, + k_last_fpr_x86_64 = lldb_xmm15_x86_64, k_first_avx_x86_64, - fpu_ymm0_x86_64 = k_first_avx_x86_64, - fpu_ymm1_x86_64, - fpu_ymm2_x86_64, - fpu_ymm3_x86_64, - fpu_ymm4_x86_64, - fpu_ymm5_x86_64, - fpu_ymm6_x86_64, - fpu_ymm7_x86_64, - fpu_ymm8_x86_64, - fpu_ymm9_x86_64, - fpu_ymm10_x86_64, - fpu_ymm11_x86_64, - fpu_ymm12_x86_64, - fpu_ymm13_x86_64, - fpu_ymm14_x86_64, - fpu_ymm15_x86_64, - k_last_avx_x86_64 = fpu_ymm15_x86_64, + lldb_ymm0_x86_64 = k_first_avx_x86_64, + lldb_ymm1_x86_64, + lldb_ymm2_x86_64, + lldb_ymm3_x86_64, + lldb_ymm4_x86_64, + lldb_ymm5_x86_64, + lldb_ymm6_x86_64, + lldb_ymm7_x86_64, + lldb_ymm8_x86_64, + lldb_ymm9_x86_64, + lldb_ymm10_x86_64, + lldb_ymm11_x86_64, + lldb_ymm12_x86_64, + lldb_ymm13_x86_64, + lldb_ymm14_x86_64, + lldb_ymm15_x86_64, + k_last_avx_x86_64 = lldb_ymm15_x86_64, - dr0_x86_64, - dr1_x86_64, - dr2_x86_64, - dr3_x86_64, - dr4_x86_64, - dr5_x86_64, - dr6_x86_64, - dr7_x86_64, + lldb_dr0_x86_64, + lldb_dr1_x86_64, + lldb_dr2_x86_64, + lldb_dr3_x86_64, + lldb_dr4_x86_64, + lldb_dr5_x86_64, + lldb_dr6_x86_64, + lldb_dr7_x86_64, k_num_registers_x86_64, k_num_gpr_registers_x86_64 = k_last_gpr_x86_64 - k_first_gpr_x86_64 + 1, diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 566816783c7e..fb39d7318a5a 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -405,14 +405,18 @@ enum { NT_AUXV }; +namespace FREEBSD { + enum { - NT_FREEBSD_PRSTATUS = 1, - NT_FREEBSD_FPREGSET, - NT_FREEBSD_PRPSINFO, - NT_FREEBSD_THRMISC = 7, - NT_FREEBSD_PROCSTAT_AUXV = 16 + NT_PRSTATUS = 1, + NT_FPREGSET, + NT_PRPSINFO, + NT_THRMISC = 7, + NT_PROCSTAT_AUXV = 16 }; +} + // Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details. static void ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data, @@ -420,6 +424,7 @@ ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data, { lldb::offset_t offset = 0; bool lp64 = (arch.GetMachine() == llvm::Triple::mips64 || + arch.GetMachine() == llvm::Triple::ppc64 || arch.GetMachine() == llvm::Triple::x86_64); int pr_version = data.GetU32(&offset); @@ -516,20 +521,20 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader * m_os = llvm::Triple::FreeBSD; switch (note.n_type) { - case NT_FREEBSD_PRSTATUS: + case FREEBSD::NT_PRSTATUS: have_prstatus = true; ParseFreeBSDPrStatus(*thread_data, note_data, arch); break; - case NT_FREEBSD_FPREGSET: + case FREEBSD::NT_FPREGSET: thread_data->fpregset = note_data; break; - case NT_FREEBSD_PRPSINFO: + case FREEBSD::NT_PRPSINFO: have_prpsinfo = true; break; - case NT_FREEBSD_THRMISC: + case FREEBSD::NT_THRMISC: ParseFreeBSDThrMisc(*thread_data, note_data); break; - case NT_FREEBSD_PROCSTAT_AUXV: + case FREEBSD::NT_PROCSTAT_AUXV: // FIXME: FreeBSD sticks an int at the beginning of the note m_auxv = DataExtractor(segment_data, note_start + 4, note_size - 4); break; diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.h b/source/Plugins/Process/elf-core/ProcessElfCore.h index 2fc2e4ee7949..7988bee5ae53 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.h +++ b/source/Plugins/Process/elf-core/ProcessElfCore.h @@ -68,52 +68,52 @@ public: //------------------------------------------------------------------ virtual bool CanDebug (lldb_private::Target &target, - bool plugin_specified_by_name); + bool plugin_specified_by_name) override; //------------------------------------------------------------------ // Creating a new process, or attaching to an existing one //------------------------------------------------------------------ virtual lldb_private::Error - DoLoadCore (); + DoLoadCore () override; virtual lldb_private::DynamicLoader * - GetDynamicLoader (); + GetDynamicLoader () override; //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ virtual lldb_private::ConstString - GetPluginName(); + GetPluginName() override; virtual uint32_t - GetPluginVersion(); + GetPluginVersion() override; //------------------------------------------------------------------ // Process Control //------------------------------------------------------------------ virtual lldb_private::Error - DoDestroy (); + DoDestroy () override; virtual void - RefreshStateAfterStop(); + RefreshStateAfterStop() override; //------------------------------------------------------------------ // Process Queries //------------------------------------------------------------------ virtual bool - IsAlive (); + IsAlive () override; //------------------------------------------------------------------ // Process Memory //------------------------------------------------------------------ virtual size_t - ReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error); + ReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override; virtual size_t - DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error); + DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override; virtual lldb::addr_t - GetImageInfoAddress (); + GetImageInfoAddress () override; lldb_private::ArchSpec GetArchitecture(); @@ -128,7 +128,7 @@ protected: virtual bool UpdateThreadList (lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list); + lldb_private::ThreadList &new_thread_list) override; private: //------------------------------------------------------------------ diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp index fbf397b933cc..f0750a0cee18 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp @@ -10,7 +10,7 @@ #include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" -#include "RegisterContextPOSIX.h" +#include "Plugins/Process/Utility/RegisterContextPOSIX.h" #include "RegisterContextPOSIXCore_mips64.h" using namespace lldb_private; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp new file mode 100644 index 000000000000..15b1b44182d7 --- /dev/null +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp @@ -0,0 +1,109 @@ +//===-- RegisterContextCorePOSIX_powerpc.cpp ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Target/Thread.h" +#include "RegisterContextPOSIX.h" +#include "RegisterContextPOSIXCore_powerpc.h" + +using namespace lldb_private; + +RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc(Thread &thread, + RegisterInfoInterface *register_info, + const DataExtractor &gpregset, + const DataExtractor &fpregset) + : RegisterContextPOSIX_powerpc(thread, 0, register_info) +{ + m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); + m_gpr.SetData(m_gpr_buffer); + m_gpr.SetByteOrder(gpregset.GetByteOrder()); + m_fpr_buffer.reset(new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); + m_fpr.SetData(m_fpr_buffer); + m_fpr.SetByteOrder(fpregset.GetByteOrder()); +} + +RegisterContextCorePOSIX_powerpc::~RegisterContextCorePOSIX_powerpc() +{ +} + +bool +RegisterContextCorePOSIX_powerpc::ReadGPR() +{ + return true; +} + +bool +RegisterContextCorePOSIX_powerpc::ReadFPR() +{ + return true; +} + +bool +RegisterContextCorePOSIX_powerpc::WriteGPR() +{ + assert(0); + return false; +} + +bool +RegisterContextCorePOSIX_powerpc::WriteFPR() +{ + assert(0); + return false; +} + +bool +RegisterContextCorePOSIX_powerpc::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) +{ + lldb::offset_t offset = reg_info->byte_offset; + if (reg_info->name[0] == 'f') { + uint64_t v = m_fpr.GetMaxU64(&offset, reg_info->byte_size); + if (offset == reg_info->byte_offset + reg_info->byte_size) + { + value = v; + return true; + } + } else { + uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); + if (offset == reg_info->byte_offset + reg_info->byte_size) + { + if (reg_info->byte_size < sizeof(v)) + value = (uint32_t)v; + else + value = v; + return true; + } + } + return false; +} + +bool +RegisterContextCorePOSIX_powerpc::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) +{ + return false; +} + +bool +RegisterContextCorePOSIX_powerpc::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) +{ + return false; +} + +bool +RegisterContextCorePOSIX_powerpc::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) +{ + return false; +} + +bool +RegisterContextCorePOSIX_powerpc::HardwareSingleStep(bool enable) +{ + return false; +} diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h new file mode 100644 index 000000000000..e6575581b360 --- /dev/null +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h @@ -0,0 +1,62 @@ +//===-- RegisterContextCorePOSIX_powerpc.h ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextCorePOSIX_powerpc_H_ +#define liblldb_RegisterContextCorePOSIX_powerpc_H_ + +#include "lldb/Core/DataBufferHeap.h" +#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h" + +class RegisterContextCorePOSIX_powerpc : + public RegisterContextPOSIX_powerpc +{ +public: + RegisterContextCorePOSIX_powerpc (lldb_private::Thread &thread, + lldb_private::RegisterInfoInterface *register_info, + const lldb_private::DataExtractor &gpregset, + const lldb_private::DataExtractor &fpregset); + + ~RegisterContextCorePOSIX_powerpc(); + + virtual bool + ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); + + virtual bool + WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); + + bool + ReadAllRegisterValues(lldb::DataBufferSP &data_sp); + + bool + WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); + + bool + HardwareSingleStep(bool enable); + +protected: + bool + ReadGPR(); + + bool + ReadFPR(); + + bool + WriteGPR(); + + bool + WriteFPR(); + +private: + lldb::DataBufferSP m_gpr_buffer; + lldb::DataBufferSP m_fpr_buffer; + lldb_private::DataExtractor m_gpr; + lldb_private::DataExtractor m_fpr; +}; + +#endif // #ifndef liblldb_RegisterContextCorePOSIX_powerpc_H_ diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp index 3e09c7bc2032..412c7ade8295 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp @@ -10,7 +10,7 @@ #include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" -#include "RegisterContextPOSIX.h" +#include "Plugins/Process/Utility/RegisterContextPOSIX.h" #include "RegisterContextPOSIXCore_x86_64.h" using namespace lldb_private; diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp index d9f6cc04a343..d62bcfcff600 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -16,11 +16,13 @@ #include "ThreadElfCore.h" #include "ProcessElfCore.h" -#include "RegisterContextLinux_x86_64.h" -#include "RegisterContextFreeBSD_i386.h" -#include "RegisterContextFreeBSD_mips64.h" -#include "RegisterContextFreeBSD_x86_64.h" +#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.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 "RegisterContextPOSIXCore_mips64.h" +#include "RegisterContextPOSIXCore_powerpc.h" #include "RegisterContextPOSIXCore_x86_64.h" using namespace lldb; @@ -94,6 +96,12 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame) { switch (arch.GetMachine()) { + case llvm::Triple::ppc: + reg_interface = new RegisterContextFreeBSD_powerpc32(arch); + break; + case llvm::Triple::ppc64: + reg_interface = new RegisterContextFreeBSD_powerpc64(arch); + break; case llvm::Triple::mips64: reg_interface = new RegisterContextFreeBSD_mips64(arch); break; @@ -138,6 +146,10 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame) case llvm::Triple::mips64: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64 (*this, reg_interface, m_gpregset_data, m_fpregset_data)); break; + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*this, reg_interface, m_gpregset_data, m_fpregset_data)); + break; case llvm::Triple::x86: case llvm::Triple::x86_64: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, reg_interface, m_gpregset_data, m_fpregset_data)); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 1f4dd93976ec..919fa5405117 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -17,15 +17,16 @@ // C++ Includes // Other libraries and framework includes -#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/Log.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSpec.h" -#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/Pipe.h" #include "lldb/Host/Socket.h" +#include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/TimeValue.h" #include "lldb/Target/Process.h" @@ -153,7 +154,6 @@ GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, m_history (512), m_send_acks (true), m_is_platform (is_platform), - m_listen_thread (LLDB_INVALID_HOST_THREAD), m_listen_url () { } @@ -227,9 +227,23 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); ConnectionStatus status = eConnectionStatusSuccess; - size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL); + const char *packet_data = packet.GetData(); + const size_t packet_length = packet.GetSize(); + size_t bytes_written = Write (packet_data, packet_length, status, NULL); if (log) { + size_t binary_start_offset = 0; + if (strncmp(packet_data, "$vFile:pwrite:", strlen("$vFile:pwrite:")) == 0) + { + const char *first_comma = strchr(packet_data, ','); + if (first_comma) + { + const char *second_comma = strchr(first_comma + 1, ','); + if (second_comma) + binary_start_offset = second_comma - packet_data + 1; + } + } + // If logging was just enabled and we have history, then dump out what // we have to the log so we get the historical context. The Dump() call that // logs all of the packet will set a boolean so that we don't dump this more @@ -237,13 +251,27 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le if (!m_history.DidDumpToLog ()) m_history.Dump (log); - log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)packet.GetSize(), packet.GetData()); + if (binary_start_offset) + { + StreamString strm; + // Print non binary data header + strm.Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)binary_start_offset, packet_data); + const uint8_t *p; + // Print binary data exactly as sent + for (p = (uint8_t*)packet_data + binary_start_offset; *p != '#'; ++p) + strm.Printf("\\x%2.2x", *p); + // Print the checksum + strm.Printf("%*s", (int)3, p); + log->PutCString(strm.GetString().c_str()); + } + else + log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)packet_length, packet_data); } - m_history.AddPacket (packet.GetString(), packet.GetSize(), History::ePacketTypeSend, bytes_written); + m_history.AddPacket (packet.GetString(), packet_length, History::ePacketTypeSend, bytes_written); - if (bytes_written == packet.GetSize()) + if (bytes_written == packet_length) { if (GetSendAcks ()) return GetAck (); @@ -253,7 +281,7 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le else { if (log) - log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData()); + log->Printf ("error: failed to send packet: %.*s", (int)packet_length, packet_data); } } return PacketResult::ErrorSendFailed; @@ -447,8 +475,8 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri } if (log) log->Printf ("GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'", - __FUNCTION__, idx, idx, m_bytes.c_str()); - m_bytes.erase(0, idx); + __FUNCTION__, idx - 1, idx - 1, m_bytes.c_str()); + m_bytes.erase(0, idx - 1); } break; } @@ -606,7 +634,7 @@ Error GDBRemoteCommunication::StartListenThread (const char *hostname, uint16_t port) { Error error; - if (IS_VALID_LLDB_HOST_THREAD(m_listen_thread)) + if (m_listen_thread.IsJoinable()) { error.SetErrorString("listen thread already running"); } @@ -619,7 +647,7 @@ GDBRemoteCommunication::StartListenThread (const char *hostname, uint16_t port) snprintf(listen_url, sizeof(listen_url), "listen://%i", port); m_listen_url = listen_url; SetConnection(new ConnectionFileDescriptor()); - m_listen_thread = Host::ThreadCreate (listen_url, GDBRemoteCommunication::ListenThread, this, &error); + m_listen_thread = ThreadLauncher::LaunchThread(listen_url, GDBRemoteCommunication::ListenThread, this, &error); } return error; } @@ -627,11 +655,8 @@ GDBRemoteCommunication::StartListenThread (const char *hostname, uint16_t port) bool GDBRemoteCommunication::JoinListenThread () { - if (IS_VALID_LLDB_HOST_THREAD(m_listen_thread)) - { - Host::ThreadJoin(m_listen_thread, NULL, NULL); - m_listen_thread = LLDB_INVALID_HOST_THREAD; - } + if (m_listen_thread.IsJoinable()) + m_listen_thread.Join(nullptr); return true; } @@ -738,6 +763,7 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, char named_pipe_path[PATH_MAX]; named_pipe_path[0] = '\0'; + Pipe port_named_pipe; bool listen = false; if (host_and_port[0]) @@ -763,15 +789,11 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, if (::mktemp (named_pipe_path)) { -#if defined(_WIN32) - if ( false ) -#else - if (::mkfifo(named_pipe_path, 0600) == 0) -#endif - { - debugserver_args.AppendArgument("--named-pipe"); - debugserver_args.AppendArgument(named_pipe_path); - } + error = port_named_pipe.CreateNew(named_pipe_path, false); + if (error.Fail()) + return error; + debugserver_args.AppendArgument("--named-pipe"); + debugserver_args.AppendArgument(named_pipe_path); } } else @@ -838,11 +860,15 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, } } while (has_env_var); - // Close STDIN, STDOUT and STDERR. We might need to redirect them - // to "/dev/null" if we run into any problems. + // Close STDIN, STDOUT and STDERR. launch_info.AppendCloseFileAction (STDIN_FILENO); launch_info.AppendCloseFileAction (STDOUT_FILENO); launch_info.AppendCloseFileAction (STDERR_FILENO); + + // Redirect STDIN, STDOUT and STDERR to "/dev/null". + launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); + launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true); + launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true); error = Host::LaunchProcess(launch_info); @@ -850,20 +876,40 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, { if (named_pipe_path[0]) { - File name_pipe_file; - error = name_pipe_file.Open(named_pipe_path, File::eOpenOptionRead); + error = port_named_pipe.OpenAsReader(named_pipe_path, false); if (error.Success()) { char port_cstr[256]; port_cstr[0] = '\0'; size_t num_bytes = sizeof(port_cstr); - error = name_pipe_file.Read(port_cstr, num_bytes); - assert (error.Success()); - assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0'); - out_port = Args::StringToUInt32(port_cstr, 0); - name_pipe_file.Close(); + // Read port from pipe with 10 second timeout. + error = port_named_pipe.ReadWithTimeout(port_cstr, num_bytes, std::chrono::microseconds(10 * 1000000), num_bytes); + if (error.Success()) + { + assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0'); + out_port = Args::StringToUInt32(port_cstr, 0); + if (log) + log->Printf("GDBRemoteCommunication::%s() debugserver listens %u port", __FUNCTION__, out_port); + } + else + { + if (log) + log->Printf("GDBRemoteCommunication::%s() failed to read a port value from named pipe %s: %s", __FUNCTION__, named_pipe_path, error.AsCString()); + + } + port_named_pipe.Close(); + } + else + { + if (log) + log->Printf("GDBRemoteCommunication::%s() failed to open named pipe %s for reading: %s", __FUNCTION__, named_pipe_path, error.AsCString()); + } + const auto err = port_named_pipe.Delete(named_pipe_path); + if (err.Fail()) + { + if (log) + log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s", __FUNCTION__, named_pipe_path, err.AsCString()); } - FileSystem::Unlink(named_pipe_path); } else if (listen) { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index b11d38563207..ac203a62788a 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -20,6 +20,7 @@ #include "lldb/lldb-public.h" #include "lldb/Core/Communication.h" #include "lldb/Core/Listener.h" +#include "lldb/Host/HostThread.h" #include "lldb/Host/Mutex.h" #include "lldb/Host/Predicate.h" #include "lldb/Host/TimeValue.h" @@ -281,8 +282,7 @@ protected: ListenThread (lldb::thread_arg_t arg); private: - - lldb::thread_t m_listen_thread; + lldb_private::HostThread m_listen_thread; std::string m_listen_url; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 5e4ed7648f95..52750de5a25f 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -20,11 +20,11 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Triple.h" #include "lldb/Interpreter/Args.h" -#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/Log.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamGDBRemote.h" #include "lldb/Core/StreamString.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Endian.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" @@ -1643,7 +1643,9 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force) } else if (name.compare("triple") == 0) { - triple.swap(value); + extractor.GetStringRef ().swap (value); + extractor.SetFilePos(0); + extractor.GetHexByteString (triple); ++num_keys_decoded; } else if (name.compare ("distribution_id") == 0) @@ -2331,6 +2333,10 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot } else if (name.compare("triple") == 0) { + StringExtractor extractor; + extractor.GetStringRef().swap(value); + extractor.SetFilePos(0); + extractor.GetHexByteString (value); process_info.GetArchitecture ().SetTriple (value.c_str()); } else if (name.compare("name") == 0) @@ -2404,6 +2410,8 @@ GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInstanceIn bool GDBRemoteCommunicationClient::GetCurrentProcessInfo () { + Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); + if (m_qProcessInfo_is_valid == eLazyBoolYes) return true; if (m_qProcessInfo_is_valid == eLazyBoolNo) @@ -2426,6 +2434,7 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo () std::string triple; uint32_t pointer_byte_size = 0; StringExtractor extractor; + ByteOrder byte_order = eByteOrderInvalid; uint32_t num_keys_decoded = 0; lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; while (response.GetNameColonValue(name, value)) @@ -2444,7 +2453,10 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo () } else if (name.compare("triple") == 0) { - triple = value; + StringExtractor extractor; + extractor.GetStringRef().swap(value); + extractor.SetFilePos(0); + extractor.GetHexByteString (triple); ++num_keys_decoded; } else if (name.compare("ostype") == 0) @@ -2459,10 +2471,15 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo () } else if (name.compare("endian") == 0) { - if (value.compare("little") == 0 || - value.compare("big") == 0 || - value.compare("pdp") == 0) - ++num_keys_decoded; + ++num_keys_decoded; + if (value.compare("little") == 0) + byte_order = eByteOrderLittle; + else if (value.compare("big") == 0) + byte_order = eByteOrderBig; + else if (value.compare("pdp") == 0) + byte_order = eByteOrderPDP; + else + --num_keys_decoded; } else if (name.compare("ptrsize") == 0) { @@ -2496,11 +2513,34 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo () } else if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() && !vendor_name.empty()) { - m_process_arch.SetArchitecture (eArchTypeMachO, cpu, sub); + llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name); + + assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat); + switch (triple.getObjectFormat()) { + case llvm::Triple::MachO: + m_process_arch.SetArchitecture (eArchTypeMachO, cpu, sub); + break; + case llvm::Triple::ELF: + m_process_arch.SetArchitecture (eArchTypeELF, cpu, sub); + break; + case llvm::Triple::COFF: + m_process_arch.SetArchitecture (eArchTypeCOFF, cpu, sub); + break; + case llvm::Triple::UnknownObjectFormat: + if (log) + log->Printf("error: failed to determine target architecture"); + return false; + } + if (pointer_byte_size) { assert (pointer_byte_size == m_process_arch.GetAddressByteSize()); } + if (byte_order != eByteOrderInvalid) + { + assert (byte_order == m_process_arch.GetByteOrder()); + } + m_process_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name)); m_process_arch.GetTriple().setOSName(llvm::StringRef (os_name)); m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name)); m_host_arch.GetTriple().setOSName (llvm::StringRef (os_name)); @@ -2931,6 +2971,11 @@ GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtracto uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, bool insert, addr_t addr, uint32_t length) { + Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64, + __FUNCTION__, insert ? "add" : "remove", addr); + // Check if the stub is known not to support this breakpoint type if (!SupportsGDBStoppointPacket(type)) return UINT8_MAX; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index ffcdd169eb9f..a7149505e869 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -23,11 +23,11 @@ // Other libraries and framework includes #include "llvm/ADT/Triple.h" #include "lldb/Interpreter/Args.h" -#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamString.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Debug.h" #include "lldb/Host/Endian.h" #include "lldb/Host/File.h" @@ -71,7 +71,7 @@ namespace //---------------------------------------------------------------------- GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) : GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform), - m_platform_sp (Platform::GetDefaultPlatform ()), + m_platform_sp (Platform::GetHostPlatform ()), m_async_thread (LLDB_INVALID_HOST_THREAD), m_process_launch_info (), m_process_launch_error (), @@ -429,6 +429,14 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, case StringExtractorGDBRemote::eServerPacketType_vAttach: packet_result = Handle_vAttach (packet); break; + + case StringExtractorGDBRemote::eServerPacketType_D: + packet_result = Handle_D (packet); + break; + + case StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo: + packet_result = Handle_qThreadStopInfo (packet); + break; } } else @@ -474,13 +482,34 @@ GDBRemoteCommunicationServer::LaunchProcess () // FIXME This looks an awful lot like we could override this in // derived classes, one for lldb-platform, the other for lldb-gdbserver. if (IsGdbServer ()) - return LaunchDebugServerProcess (); + return LaunchProcessForDebugging (); else return LaunchPlatformProcess (); } +bool +GDBRemoteCommunicationServer::ShouldRedirectInferiorOutputOverGdbRemote (const lldb_private::ProcessLaunchInfo &launch_info) const +{ + // Retrieve the file actions specified for stdout and stderr. + auto stdout_file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); + auto stderr_file_action = launch_info.GetFileActionForFD (STDERR_FILENO); + + // If neither stdout and stderr file actions are specified, we're not doing anything special, so + // assume we want to redirect stdout/stderr over gdb-remote $O messages. + if ((stdout_file_action == nullptr) && (stderr_file_action == nullptr)) + { + // Send stdout/stderr over the gdb-remote protocol. + return true; + } + + // Any other setting for either stdout or stderr implies we are either suppressing + // it (with /dev/null) or we've got it set to a PTY. Either way, we don't want the + // output over gdb-remote. + return false; +} + lldb_private::Error -GDBRemoteCommunicationServer::LaunchDebugServerProcess () +GDBRemoteCommunicationServer::LaunchProcessForDebugging () { Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); @@ -503,20 +532,34 @@ GDBRemoteCommunicationServer::LaunchDebugServerProcess () return error; } - // Setup stdout/stderr mapping from inferior. - auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor (); - if (terminal_fd >= 0) + // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as needed. + // llgs local-process debugging may specify PTYs, which will eliminate the need to reflect inferior + // stdout/stderr over the gdb-remote protocol. + if (ShouldRedirectInferiorOutputOverGdbRemote (m_process_launch_info)) { if (log) - log->Printf ("ProcessGDBRemoteCommunicationServer::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd); - error = SetSTDIOFileDescriptor (terminal_fd); - if (error.Fail ()) - return error; + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " setting up stdout/stderr redirection via $O gdb-remote commands", __FUNCTION__, m_debugged_process_sp->GetID ()); + + // Setup stdout/stderr mapping from inferior to $O + auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor (); + if (terminal_fd >= 0) + { + if (log) + log->Printf ("ProcessGDBRemoteCommunicationServer::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd); + error = SetSTDIOFileDescriptor (terminal_fd); + if (error.Fail ()) + return error; + } + else + { + if (log) + log->Printf ("ProcessGDBRemoteCommunicationServer::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd); + } } else { if (log) - log->Printf ("ProcessGDBRemoteCommunicationServer::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd); + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " skipping stdout/stderr redirection via $O: inferior will communicate over client-provided file descriptors", __FUNCTION__, m_debugged_process_sp->GetID ()); } printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID ()); @@ -526,33 +569,10 @@ GDBRemoteCommunicationServer::LaunchDebugServerProcess () if ((pid = m_process_launch_info.GetProcessID ()) != LLDB_INVALID_PROCESS_ID) { // add to spawned pids - { - Mutex::Locker locker (m_spawned_pids_mutex); - // On an lldb-gdbserver, we would expect there to be only one. - assert (m_spawned_pids.empty () && "lldb-gdbserver adding tracked process but one already existed"); - m_spawned_pids.insert (pid); - } - } - - if (error.Success ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServer::%s beginning check to wait for launched application to hit first stop", __FUNCTION__); - - int iteration = 0; - // Wait for the process to hit its first stop state. - while (!StateIsStoppedState (m_debugged_process_sp->GetState (), false)) - { - if (log) - log->Printf ("GDBRemoteCommunicationServer::%s waiting for launched process to hit first stop (%d)...", __FUNCTION__, iteration++); - - // FIXME use a finer granularity. - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - - if (log) - log->Printf ("GDBRemoteCommunicationServer::%s launched application has hit first stop", __FUNCTION__); - + Mutex::Locker locker (m_spawned_pids_mutex); + // On an lldb-gdbserver, we would expect there to be only one. + assert (m_spawned_pids.empty () && "lldb-gdbserver adding tracked process but one already existed"); + m_spawned_pids.insert (pid); } return error; @@ -699,12 +719,18 @@ GDBRemoteCommunicationServer::SendWResponse (lldb_private::NativeProcessProtocol char return_type_code; switch (exit_type) { - case ExitType::eExitTypeExit: return_type_code = 'W'; break; - case ExitType::eExitTypeSignal: return_type_code = 'X'; break; - case ExitType::eExitTypeStop: return_type_code = 'S'; break; - + case ExitType::eExitTypeExit: + return_type_code = 'W'; + break; + case ExitType::eExitTypeSignal: + return_type_code = 'X'; + break; + case ExitType::eExitTypeStop: + return_type_code = 'S'; + break; case ExitType::eExitTypeInvalid: - default: return_type_code = 'E'; break; + return_type_code = 'E'; + break; } response.PutChar (return_type_code); @@ -861,21 +887,21 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid) response.Printf ("thread:%" PRIx64 ";", tid); // Include the thread name if there is one. - const char *thread_name = thread_sp->GetName (); - if (thread_name && thread_name[0]) + const std::string thread_name = thread_sp->GetName (); + if (!thread_name.empty ()) { - size_t thread_name_len = strlen(thread_name); + size_t thread_name_len = thread_name.length (); - if (::strcspn (thread_name, "$#+-;:") == thread_name_len) + if (::strcspn (thread_name.c_str (), "$#+-;:") == thread_name_len) { response.PutCString ("name:"); - response.PutCString (thread_name); + response.PutCString (thread_name.c_str ()); } else { // The thread name contains special chars, send as hex bytes. response.PutCString ("hexname:"); - response.PutCStringAsRawHex8 (thread_name); + response.PutCStringAsRawHex8 (thread_name.c_str ()); } response.PutChar (';'); } @@ -1197,7 +1223,7 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet ArchSpec host_arch(HostInfo::GetArchitecture()); const llvm::Triple &host_triple = host_arch.GetTriple(); response.PutCString("triple:"); - response.PutCString(host_triple.getTriple().c_str()); + response.PutCStringAsRawHex8(host_triple.getTriple().c_str()); response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize()); const char* distribution_id = host_arch.GetDistributionId ().AsCString (); @@ -1252,7 +1278,6 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet } std::string s; -#if !defined(__linux__) if (HostInfo::GetOSBuildString(s)) { response.PutCString ("os_build:"); @@ -1265,7 +1290,6 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet response.PutCStringAsRawHex8(s.c_str()); response.PutChar(';'); } -#endif #if defined(__APPLE__) @@ -1315,7 +1339,7 @@ CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &r { const llvm::Triple &proc_triple = proc_arch.GetTriple(); response.PutCString("triple:"); - response.PutCString(proc_triple.getTriple().c_str()); + response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); response.PutChar(';'); } } @@ -1351,7 +1375,10 @@ CreateProcessInfoResponse_DebugServerStyle (const ProcessInstanceInfo &proc_info response.Printf ("vendor:%s;", vendor.c_str ()); #else // We'll send the triple. - response.Printf ("triple:%s;", proc_triple.getTriple().c_str ()); + response.PutCString("triple:"); + response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); + response.PutChar(';'); + #endif std::string ostype = proc_triple.getOSName (); // Adjust so ostype reports ios for Apple/ARM and Apple/ARM64. @@ -2372,8 +2399,6 @@ GDBRemoteCommunicationServer::Handle_vCont_actions (StringExtractorGDBRemote &pa return SendUnimplementedResponse (packet.GetStringRef().c_str()); } - // We handle $vCont messages for c. - // TODO add C, s and S. StreamString response; response.Printf("vCont;c;C;s;S"); @@ -3388,10 +3413,8 @@ GDBRemoteCommunicationServer::Handle_interrupt (StringExtractorGDBRemote &packet return SendErrorResponse (0x15); } - // Build the ResumeActionList - stop everything. - lldb_private::ResumeActionList actions (StateType::eStateStopped, 0); - - Error error = m_debugged_process_sp->Resume (actions); + // Interrupt the process. + Error error = m_debugged_process_sp->Interrupt (); if (error.Fail ()) { if (log) @@ -3771,7 +3794,7 @@ GDBRemoteCommunicationServer::Handle_z (StringExtractorGDBRemote &packet) } // Parse out software or hardware breakpoint requested. - packet.SetFilePos (strlen("Z")); + packet.SetFilePos (strlen("z")); if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short z packet, missing software/hardware specifier"); @@ -3811,7 +3834,7 @@ GDBRemoteCommunicationServer::Handle_z (StringExtractorGDBRemote &packet) if (want_breakpoint) { - // Try to set the breakpoint. + // Try to clear the breakpoint. const Error error = m_debugged_process_sp->RemoveBreakpoint (breakpoint_addr); if (error.Success ()) return SendOKResponse (); @@ -4171,8 +4194,93 @@ GDBRemoteCommunicationServer::Handle_vAttach (StringExtractorGDBRemote &packet) // Notify we attached by sending a stop packet. return SendStopReasonForState (m_debugged_process_sp->GetState (), true); +} - return PacketResult::Success; +GDBRemoteCommunicationServer::PacketResult +GDBRemoteCommunicationServer::Handle_D (StringExtractorGDBRemote &packet) +{ + Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS)); + + // We don't support if we're not llgs. + if (!IsGdbServer()) + return SendUnimplementedResponse ("only supported for lldb-gdbserver"); + + // Scope for mutex locker. + Mutex::Locker locker (m_spawned_pids_mutex); + + // Fail if we don't have a current process. + if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) + { + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__); + return SendErrorResponse (0x15); + } + + if (m_spawned_pids.find(m_debugged_process_sp->GetID ()) == m_spawned_pids.end()) + { + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s failed to find PID %" PRIu64 " in spawned pids list", + __FUNCTION__, m_debugged_process_sp->GetID ()); + return SendErrorResponse (0x1); + } + + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + + // Consume the ';' after D. + packet.SetFilePos (1); + if (packet.GetBytesLeft ()) + { + if (packet.GetChar () != ';') + return SendIllFormedResponse (packet, "D missing expected ';'"); + + // Grab the PID from which we will detach (assume hex encoding). + pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID, 16); + if (pid == LLDB_INVALID_PROCESS_ID) + return SendIllFormedResponse (packet, "D failed to parse the process id"); + } + + if (pid != LLDB_INVALID_PROCESS_ID && + m_debugged_process_sp->GetID () != pid) + { + return SendIllFormedResponse (packet, "Invalid pid"); + } + + if (m_stdio_communication.IsConnected ()) + { + m_stdio_communication.StopReadThread (); + } + + const Error error = m_debugged_process_sp->Detach (); + if (error.Fail ()) + { + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s failed to detach from pid %" PRIu64 ": %s\n", + __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ()); + return SendErrorResponse (0x01); + } + + m_spawned_pids.erase (m_debugged_process_sp->GetID ()); + return SendOKResponse (); +} + +GDBRemoteCommunicationServer::PacketResult +GDBRemoteCommunicationServer::Handle_qThreadStopInfo (StringExtractorGDBRemote &packet) +{ + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + + // We don't support if we're not llgs. + if (!IsGdbServer()) + return SendUnimplementedResponse ("only supported for lldb-gdbserver"); + + packet.SetFilePos (strlen("qThreadStopInfo")); + const lldb::tid_t tid = packet.GetHexMaxU32 (false, LLDB_INVALID_THREAD_ID); + if (tid == LLDB_INVALID_THREAD_ID) + { + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s failed, could not parse thread id from request \"%s\"", __FUNCTION__, packet.GetStringRef ().c_str ()); + return SendErrorResponse (0x15); + } + return SendStopReplyPacketForThread (tid); } void diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 13c037c0287b..07ce98e29ac6 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -58,7 +58,7 @@ public: bool &quit); virtual bool - GetThreadSuffixSupported () + GetThreadSuffixSupported () override { return true; } @@ -152,8 +152,6 @@ public: //------------------------------------------------------------------ /// Specify the program to launch and its arguments. /// - /// The LaunchProcess () command can be executed to do the lauching. - /// /// @param[in] args /// The command line to launch. /// @@ -170,8 +168,6 @@ public: //------------------------------------------------------------------ /// Specify the launch flags for the process. /// - /// The LaunchProcess () command can be executed to do the lauching. - /// /// @param[in] launch_flags /// The launch flags to use when launching this process. /// @@ -463,6 +459,12 @@ protected: PacketResult Handle_vAttach (StringExtractorGDBRemote &packet); + PacketResult + Handle_D (StringExtractorGDBRemote &packet); + + PacketResult + Handle_qThreadStopInfo (StringExtractorGDBRemote &packet); + void SetCurrentThreadID (lldb::tid_t tid); @@ -511,9 +513,9 @@ private: return !m_is_platform; } - /// Launch a process from lldb-gdbserver + /// Launch an inferior process from lldb-gdbserver lldb_private::Error - LaunchDebugServerProcess (); + LaunchProcessForDebugging (); /// Launch a process from lldb-platform lldb_private::Error @@ -540,6 +542,9 @@ private: void ClearProcessSpecificData (); + bool + ShouldRedirectInferiorOutputOverGdbRemote (const lldb_private::ProcessLaunchInfo &launch_info) const; + //------------------------------------------------------------------ // For GDBRemoteCommunicationServer only //------------------------------------------------------------------ diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index f35d954caa7b..fe99706969c8 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -14,7 +14,6 @@ #include #include #ifndef LLDB_DISABLE_POSIX -#include #include #include // for mmap #endif @@ -32,7 +31,7 @@ #include "lldb/Interpreter/Args.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/ConnectionFileDescriptor.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -42,7 +41,9 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" #include "lldb/Core/Value.h" +#include "lldb/Host/HostThread.h" #include "lldb/Host/Symbols.h" +#include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/TimeValue.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandObject.h" @@ -272,8 +273,6 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) : m_last_stop_packet_mutex (Mutex::eMutexTypeNormal), m_register_info (), m_async_broadcaster (NULL, "lldb.process.gdb-remote.async-broadcaster"), - m_async_thread (LLDB_INVALID_HOST_THREAD), - m_async_thread_state(eAsyncThreadNotStarted), m_async_thread_state_mutex(Mutex::eMutexTypeRecursive), m_thread_ids (), m_continue_c_tids (), @@ -749,8 +748,12 @@ ProcessGDBRemote::WillLaunchOrAttach () Error ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info) { + Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); Error error; + if (log) + log->Printf ("ProcessGDBRemote::%s() entered", __FUNCTION__); + uint32_t launch_flags = launch_info.GetFlags().Get(); const char *stdin_path = NULL; const char *stdout_path = NULL; @@ -777,10 +780,21 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info) stderr_path = file_action->GetPath(); } + if (log) + { + if (stdin_path || stdout_path || stderr_path) + log->Printf ("ProcessGDBRemote::%s provided with STDIO paths via launch_info: stdin=%s, stdout=%s, stdout=%s", + __FUNCTION__, + stdin_path ? stdin_path : "", + stdout_path ? stdout_path : "", + stderr_path ? stderr_path : ""); + else + log->Printf ("ProcessGDBRemote::%s no STDIO paths given via launch_info", __FUNCTION__); + } + // ::LogSetBitMask (GDBR_LOG_DEFAULT); // ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD); // ::LogSetLogFile ("/dev/stdout"); - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); ObjectFile * object_file = exe_module->GetObjectFile(); if (object_file) @@ -817,6 +831,13 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info) if (stderr_path == NULL) stderr_path = slave_name; + + if (log) + log->Printf ("ProcessGDBRemote::%s adjusted STDIO paths for local platform (IsHost() is true) using slave: stdin=%s, stdout=%s, stdout=%s", + __FUNCTION__, + stdin_path ? stdin_path : "", + stdout_path ? stdout_path : "", + stderr_path ? stderr_path : ""); } // Set STDIN to /dev/null if we want STDIO disabled or if either @@ -834,7 +855,14 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info) if (disable_stdio || (stderr_path == NULL && (stdin_path || stdout_path))) stderr_path = "/dev/null"; - if (stdin_path) + if (log) + log->Printf ("ProcessGDBRemote::%s final STDIO paths after all adjustments: stdin=%s, stdout=%s, stdout=%s", + __FUNCTION__, + stdin_path ? stdin_path : "", + stdout_path ? stdout_path : "", + stderr_path ? stderr_path : ""); + + if (stdin_path) m_gdb_comm.SetSTDIN (stdin_path); if (stdout_path) m_gdb_comm.SetSTDOUT (stdout_path); @@ -1026,18 +1054,38 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch) // prefer that over the Host information as it will be more specific // to our process. - if (m_gdb_comm.GetProcessArchitecture().IsValid()) - process_arch = m_gdb_comm.GetProcessArchitecture(); + const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); + if (remote_process_arch.IsValid()) + { + process_arch = remote_process_arch; + if (log) + log->Printf ("ProcessGDBRemote::%s gdb-remote had process architecture, using %s %s", + __FUNCTION__, + process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "", + process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : ""); + } else + { process_arch = m_gdb_comm.GetHostArchitecture(); + if (log) + log->Printf ("ProcessGDBRemote::%s gdb-remote did not have process architecture, using gdb-remote host architecture %s %s", + __FUNCTION__, + process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "", + process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : ""); + } if (process_arch.IsValid()) { ArchSpec &target_arch = GetTarget().GetArchitecture(); - if (target_arch.IsValid()) { - // If the remote host is ARM and we have apple as the vendor, then + if (log) + log->Printf ("ProcessGDBRemote::%s analyzing target arch, currently %s %s", + __FUNCTION__, + target_arch.GetArchitectureName () ? target_arch.GetArchitectureName () : "", + target_arch.GetTriple().getTriple ().c_str() ? target_arch.GetTriple().getTriple ().c_str() : ""); + + // If the remote host is ARM and we have apple as the vendor, then // ARM executables and shared libraries can have mixed ARM architectures. // You can have an armv6 executable, and if the host is armv7, then the // system will load the best possible architecture for all shared libraries @@ -1048,6 +1096,11 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch) process_arch.GetTriple().getVendor() == llvm::Triple::Apple) { GetTarget().SetArchitecture (process_arch); + if (log) + log->Printf ("ProcessGDBRemote::%s remote process is ARM/Apple, setting target arch to %s %s", + __FUNCTION__, + process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "", + process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : ""); } else { @@ -1066,7 +1119,14 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch) target_triple.setEnvironment (remote_triple.getEnvironment()); } } + } + + if (log) + log->Printf ("ProcessGDBRemote::%s final target arch after adjustments for remote architecture: %s %s", + __FUNCTION__, + target_arch.GetArchitectureName () ? target_arch.GetArchitectureName () : "", + target_arch.GetTriple().getTriple ().c_str() ? target_arch.GetTriple().getTriple ().c_str() : ""); } else { @@ -1095,7 +1155,12 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid) Error ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) { + Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); Error error; + + if (log) + log->Printf ("ProcessGDBRemote::%s()", __FUNCTION__); + // Clear out and clean up from any current state Clear(); if (attach_pid != LLDB_INVALID_PROCESS_ID) @@ -1118,13 +1183,14 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process if (error.Success()) { m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError()); - + char packet[64]; const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid); SetID (attach_pid); m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len)); } } + return error; } @@ -1432,7 +1498,7 @@ ProcessGDBRemote::DoResume () TimeValue timeout; timeout = TimeValue::Now(); timeout.OffsetWithSeconds (5); - if (!IS_VALID_LLDB_HOST_THREAD(m_async_thread)) + if (!m_async_thread.IsJoinable()) { error.SetErrorString ("Trying to resume but the async thread is dead."); if (log) @@ -2891,30 +2957,17 @@ ProcessGDBRemote::StartAsyncThread () log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__); Mutex::Locker start_locker(m_async_thread_state_mutex); - if (m_async_thread_state == eAsyncThreadNotStarted) + if (!m_async_thread.IsJoinable()) { // Create a thread that watches our internal state and controls which // events make it to clients (into the DCProcess event queue). - m_async_thread = Host::ThreadCreate ("", ProcessGDBRemote::AsyncThread, this, NULL); - if (IS_VALID_LLDB_HOST_THREAD(m_async_thread)) - { - m_async_thread_state = eAsyncThreadRunning; - return true; - } - else - return false; - } - else - { - // Somebody tried to start the async thread while it was either being started or stopped. If the former, and - // it started up successfully, then say all's well. Otherwise it is an error, since we aren't going to restart it. - if (log) - log->Printf ("ProcessGDBRemote::%s () - Called when Async thread was in state: %d.", __FUNCTION__, m_async_thread_state); - if (m_async_thread_state == eAsyncThreadRunning) - return true; - else - return false; + + m_async_thread = ThreadLauncher::LaunchThread("", ProcessGDBRemote::AsyncThread, this, NULL); } + else if (log) + log->Printf("ProcessGDBRemote::%s () - Called when Async thread was already running.", __FUNCTION__); + + return m_async_thread.IsJoinable(); } void @@ -2926,7 +2979,7 @@ ProcessGDBRemote::StopAsyncThread () log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__); Mutex::Locker start_locker(m_async_thread_state_mutex); - if (m_async_thread_state == eAsyncThreadRunning) + if (m_async_thread.IsJoinable()) { m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit); @@ -2934,17 +2987,10 @@ ProcessGDBRemote::StopAsyncThread () m_gdb_comm.Disconnect(); // Disconnect from the debug server. // Stop the stdio thread - if (IS_VALID_LLDB_HOST_THREAD(m_async_thread)) - { - Host::ThreadJoin (m_async_thread, NULL, NULL); - } - m_async_thread_state = eAsyncThreadDone; - } - else - { - if (log) - log->Printf ("ProcessGDBRemote::%s () - Called when Async thread was in state: %d.", __FUNCTION__, m_async_thread_state); + m_async_thread.Join(nullptr); } + else if (log) + log->Printf("ProcessGDBRemote::%s () - Called when Async thread was not running.", __FUNCTION__); } @@ -3086,7 +3132,7 @@ ProcessGDBRemote::AsyncThread (void *arg) if (log) log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread exiting...", __FUNCTION__, arg, process->GetID()); - process->m_async_thread = LLDB_INVALID_HOST_THREAD; + process->m_async_thread.Reset(); return NULL; } diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 942b31c84dde..e0c460a202d6 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -25,6 +25,7 @@ #include "lldb/Core/StringList.h" #include "lldb/Core/StructuredData.h" #include "lldb/Core/ThreadSafeValue.h" +#include "lldb/Host/HostThread.h" #include "lldb/lldb-private-forward.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" @@ -74,148 +75,148 @@ public: //------------------------------------------------------------------ virtual bool CanDebug (lldb_private::Target &target, - bool plugin_specified_by_name); + bool plugin_specified_by_name) override; virtual lldb_private::CommandObject * - GetPluginCommandObject(); + GetPluginCommandObject() override; //------------------------------------------------------------------ // Creating a new process, or attaching to an existing one //------------------------------------------------------------------ virtual lldb_private::Error - WillLaunch (lldb_private::Module* module); + WillLaunch (lldb_private::Module* module) override; virtual lldb_private::Error DoLaunch (lldb_private::Module *exe_module, - lldb_private::ProcessLaunchInfo &launch_info); + lldb_private::ProcessLaunchInfo &launch_info) override; virtual void - DidLaunch (); + DidLaunch () override; virtual lldb_private::Error - WillAttachToProcessWithID (lldb::pid_t pid); + WillAttachToProcessWithID (lldb::pid_t pid) override; virtual lldb_private::Error - WillAttachToProcessWithName (const char *process_name, bool wait_for_launch); + WillAttachToProcessWithName (const char *process_name, bool wait_for_launch) override; virtual lldb_private::Error - DoConnectRemote (lldb_private::Stream *strm, const char *remote_url); + DoConnectRemote (lldb_private::Stream *strm, const char *remote_url) override; lldb_private::Error WillLaunchOrAttach (); virtual lldb_private::Error - DoAttachToProcessWithID (lldb::pid_t pid); + DoAttachToProcessWithID (lldb::pid_t pid) override; virtual lldb_private::Error - DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info); + DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override; virtual lldb_private::Error DoAttachToProcessWithName (const char *process_name, - const lldb_private::ProcessAttachInfo &attach_info); + const lldb_private::ProcessAttachInfo &attach_info) override; virtual void - DidAttach (lldb_private::ArchSpec &process_arch); + DidAttach (lldb_private::ArchSpec &process_arch) override; //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ virtual lldb_private::ConstString - GetPluginName(); + GetPluginName() override; virtual uint32_t - GetPluginVersion(); + GetPluginVersion() override; //------------------------------------------------------------------ // Process Control //------------------------------------------------------------------ virtual lldb_private::Error - WillResume (); + WillResume () override; virtual lldb_private::Error - DoResume (); + DoResume () override; virtual lldb_private::Error - DoHalt (bool &caused_stop); + DoHalt (bool &caused_stop) override; virtual lldb_private::Error - DoDetach (bool keep_stopped); + DoDetach (bool keep_stopped) override; virtual bool - DetachRequiresHalt() { return true; } + DetachRequiresHalt() override { return true; } virtual lldb_private::Error - DoSignal (int signal); + DoSignal (int signal) override; virtual lldb_private::Error - DoDestroy (); + DoDestroy () override; virtual void - RefreshStateAfterStop(); + RefreshStateAfterStop() override; //------------------------------------------------------------------ // Process Queries //------------------------------------------------------------------ virtual bool - IsAlive (); + IsAlive () override; virtual lldb::addr_t - GetImageInfoAddress(); + GetImageInfoAddress() override; //------------------------------------------------------------------ // Process Memory //------------------------------------------------------------------ virtual size_t - DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error); + DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override; virtual size_t - DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, lldb_private::Error &error); + DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, lldb_private::Error &error) override; virtual lldb::addr_t - DoAllocateMemory (size_t size, uint32_t permissions, lldb_private::Error &error); + DoAllocateMemory (size_t size, uint32_t permissions, lldb_private::Error &error) override; virtual lldb_private::Error GetMemoryRegionInfo (lldb::addr_t load_addr, - lldb_private::MemoryRegionInfo ®ion_info); + lldb_private::MemoryRegionInfo ®ion_info) override; virtual lldb_private::Error - DoDeallocateMemory (lldb::addr_t ptr); + DoDeallocateMemory (lldb::addr_t ptr) override; //------------------------------------------------------------------ // Process STDIO //------------------------------------------------------------------ virtual size_t - PutSTDIN (const char *buf, size_t buf_size, lldb_private::Error &error); + PutSTDIN (const char *buf, size_t buf_size, lldb_private::Error &error) override; //---------------------------------------------------------------------- // Process Breakpoints //---------------------------------------------------------------------- virtual lldb_private::Error - EnableBreakpointSite (lldb_private::BreakpointSite *bp_site); + EnableBreakpointSite (lldb_private::BreakpointSite *bp_site) override; virtual lldb_private::Error - DisableBreakpointSite (lldb_private::BreakpointSite *bp_site); + DisableBreakpointSite (lldb_private::BreakpointSite *bp_site) override; //---------------------------------------------------------------------- // Process Watchpoints //---------------------------------------------------------------------- virtual lldb_private::Error - EnableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true); + EnableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true) override; virtual lldb_private::Error - DisableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true); + DisableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true) override; virtual lldb_private::Error - GetWatchpointSupportInfo (uint32_t &num); + GetWatchpointSupportInfo (uint32_t &num) override; virtual lldb_private::Error - GetWatchpointSupportInfo (uint32_t &num, bool& after); + GetWatchpointSupportInfo (uint32_t &num, bool& after) override; virtual bool - StartNoticingNewThreads(); + StartNoticingNewThreads() override; virtual bool - StopNoticingNewThreads(); + StopNoticingNewThreads() override; GDBRemoteCommunicationClient & GetGDBRemote() @@ -224,13 +225,13 @@ public: } virtual lldb_private::Error - SendEventData(const char *data); + SendEventData(const char *data) override; //---------------------------------------------------------------------- // Override SetExitStatus so we can disconnect from the remote GDB server //---------------------------------------------------------------------- virtual bool - SetExitStatus (int exit_status, const char *cstr); + SetExitStatus (int exit_status, const char *cstr) override; void SetUserSpecifiedMaxMemoryTransferSize (uint64_t user_specified_max); @@ -286,7 +287,7 @@ protected: virtual bool UpdateThreadList (lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list); + lldb_private::ThreadList &new_thread_list) override; lldb_private::Error LaunchAndConnectToDebugserver (const lldb_private::ProcessInfo &process_info); @@ -324,23 +325,15 @@ protected: eBroadcastBitAsyncThreadShouldExit = (1 << 1), eBroadcastBitAsyncThreadDidExit = (1 << 2) }; - - typedef enum AsyncThreadState - { - eAsyncThreadNotStarted, - eAsyncThreadRunning, - eAsyncThreadDone - } AsyncThreadState; lldb_private::Flags m_flags; // Process specific flags (see eFlags enums) GDBRemoteCommunicationClient m_gdb_comm; - lldb::pid_t m_debugserver_pid; + std::atomic m_debugserver_pid; StringExtractorGDBRemote m_last_stop_packet; lldb_private::Mutex m_last_stop_packet_mutex; GDBRemoteDynamicRegisterInfo m_register_info; lldb_private::Broadcaster m_async_broadcaster; - lldb::thread_t m_async_thread; - AsyncThreadState m_async_thread_state; + lldb_private::HostThread m_async_thread; lldb_private::Mutex m_async_thread_state_mutex; typedef std::vector tid_collection; typedef std::vector< std::pair > tid_sig_collection; @@ -395,7 +388,7 @@ protected: std::string &dispatch_queue_name); lldb_private::DynamicLoader * - GetDynamicLoader (); + GetDynamicLoader () override; private: //------------------------------------------------------------------ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp index bc2e7a62b76e..14fc2cea2329 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp @@ -73,14 +73,14 @@ DWARFAbbreviationDeclaration::Extract(const DWARFDataExtractor& data, lldb::offs void DWARFAbbreviationDeclaration::Dump(Stream *s) const { -// *ostrm_ptr << std::setfill(' ') << std::dec << '[' << std::setw(3) << std::right << m_code << ']' << ' ' << std::setw(30) << std::left << DW_TAG_value_to_name(m_tag) << DW_CHILDREN_value_to_name(m_has_children) << std::endl; -// -// DWARFAttribute::const_iterator pos; -// -// for (pos = m_attributes.begin(); pos != m_attributes.end(); ++pos) -// *ostrm_ptr << " " << std::setw(29) << std::left << DW_AT_value_to_name(pos->attr()) << ' ' << DW_FORM_value_to_name(pos->form()) << std::endl; -// -// *ostrm_ptr << std::endl; + s->Printf("Debug Abbreviation Declaration: code = 0x%4.4x, tag = %s, has_children = %s\n", m_code, DW_TAG_value_to_name(m_tag), DW_CHILDREN_value_to_name(m_has_children)); + + DWARFAttribute::const_iterator pos; + + for (pos = m_attributes.begin(); pos != m_attributes.end(); ++pos) + s->Printf(" attr = %s, form = %s\n", DW_AT_value_to_name(pos->get_attr()), DW_FORM_value_to_name(pos->get_form())); + + s->Printf("\n"); } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index b2e64ad9f8c8..067449a289be 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -49,7 +49,8 @@ DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF* dwarf2Data) : m_producer (eProducerInvalid), m_producer_version_major (0), m_producer_version_minor (0), - m_producer_version_update (0) + m_producer_version_update (0), + m_is_dwarf64 (false) { } @@ -66,6 +67,7 @@ DWARFCompileUnit::Clear() m_func_aranges_ap.reset(); m_user_data = NULL; m_producer = eProducerInvalid; + m_is_dwarf64 = false; } bool @@ -79,9 +81,10 @@ DWARFCompileUnit::Extract(const DWARFDataExtractor &debug_info, lldb::offset_t * { dw_offset_t abbr_offset; const DWARFDebugAbbrev *abbr = m_dwarf2Data->DebugAbbrev(); - m_length = debug_info.GetU32(offset_ptr); + m_length = debug_info.GetDWARFInitialLength(offset_ptr); + m_is_dwarf64 = debug_info.IsDWARF64(); m_version = debug_info.GetU16(offset_ptr); - abbr_offset = debug_info.GetU32(offset_ptr); + abbr_offset = debug_info.GetDWARFOffset(offset_ptr); m_addr_size = debug_info.GetU8 (offset_ptr); bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1); @@ -168,7 +171,7 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only) die_index_stack.reserve(32); die_index_stack.push_back(0); bool prev_die_had_children = false; - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize()); + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64); while (offset < next_cu_offset && die.FastExtract (debug_info_data, this, fixed_form_sizes, &offset)) { @@ -347,6 +350,14 @@ DWARFCompileUnit::GetAddressByteSize(const DWARFCompileUnit* cu) return DWARFCompileUnit::GetDefaultAddressSize(); } +bool +DWARFCompileUnit::IsDWARF64(const DWARFCompileUnit* cu) +{ + if (cu) + return cu->IsDWARF64(); + return false; +} + uint8_t DWARFCompileUnit::GetDefaultAddressSize() { @@ -619,7 +630,7 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, { const DWARFDataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data(); - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize()); + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64); Log *log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_LOOKUPS)); @@ -761,7 +772,7 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, case DW_AT_specification: if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) - specification_die_offset = form_value.Reference(this); + specification_die_offset = form_value.Reference(); break; } } @@ -1030,3 +1041,9 @@ DWARFCompileUnit::GetProducerVersionUpdate() return m_producer_version_update; } +bool +DWARFCompileUnit::IsDWARF64() const +{ + return m_is_dwarf64; +} + diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h index ed1894b8a9f6..3e904892dbd5 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -41,11 +41,11 @@ public: bool Verify(lldb_private::Stream *s) const; void Dump(lldb_private::Stream *s) const; dw_offset_t GetOffset() const { return m_offset; } - uint32_t Size() const { return 11; /* Size in bytes of the compile unit header */ } + uint32_t Size() const { return m_is_dwarf64 ? 23 : 11; /* Size in bytes of the compile unit header */ } bool ContainsDIEOffset(dw_offset_t die_offset) const { return die_offset >= GetFirstDIEOffset() && die_offset < GetNextCompileUnitOffset(); } dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); } - dw_offset_t GetNextCompileUnitOffset() const { return m_offset + m_length + 4; } - size_t GetDebugInfoSize() const { return m_length + 4 - Size(); /* Size in bytes of the .debug_info data associated with this compile unit. */ } + dw_offset_t GetNextCompileUnitOffset() const { return m_offset + m_length + (m_is_dwarf64 ? 12 : 4); } + size_t GetDebugInfoSize() const { return m_length + (m_is_dwarf64 ? 12 : 4) - Size(); /* Size in bytes of the .debug_info data associated with this compile unit. */ } uint32_t GetLength() const { return m_length; } uint16_t GetVersion() const { return m_version; } const DWARFAbbreviationDeclarationSet* GetAbbreviations() const { return m_abbrevs; } @@ -118,6 +118,9 @@ public: static uint8_t GetAddressByteSize(const DWARFCompileUnit* cu); + static bool + IsDWARF64(const DWARFCompileUnit* cu); + static uint8_t GetDefaultAddressSize(); @@ -183,6 +186,9 @@ public: uint32_t GetProducerVersionUpdate(); + bool + IsDWARF64() const; + protected: SymbolFileDWARF* m_dwarf2Data; const DWARFAbbreviationDeclarationSet *m_abbrevs; @@ -191,13 +197,14 @@ protected: std::unique_ptr m_func_aranges_ap; // A table similar to the .debug_aranges table, but this one points to the exact DW_TAG_subprogram DIEs dw_addr_t m_base_addr; dw_offset_t m_offset; - uint32_t m_length; + dw_offset_t m_length; uint16_t m_version; uint8_t m_addr_size; Producer m_producer; uint32_t m_producer_version_major; uint32_t m_producer_version_minor; uint32_t m_producer_version_update; + bool m_is_dwarf64; void ParseProducerInfo (); diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h index 6e5b974a71ff..ba2e8ad08acc 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h @@ -33,6 +33,9 @@ public: size_t GetDWARFSizeofInitialLength() const { return m_is_dwarf64 ? 12 : 4; } + bool + IsDWARF64() const { return m_is_dwarf64; } + protected: mutable bool m_is_dwarf64; }; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index a8c553e2d2ca..393434800c01 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -555,8 +555,15 @@ static dw_offset_t DumpCallback if (dumpInfo->die_offset == DW_INVALID_OFFSET) { // We are dumping everything - cu->Dump(s); - return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this Compile Unit + if (cu) + { + cu->Dump(s); + return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this Compile Unit + } + else + { + return DW_INVALID_OFFSET; + } } else { @@ -568,7 +575,7 @@ static dw_offset_t DumpCallback // We are dumping only a single DIE possibly with it's children and // we must find it's compile unit before we can dump it properly - if (dumpInfo->die_offset < cu->GetFirstDIEOffset()) + if (cu && dumpInfo->die_offset < cu->GetFirstDIEOffset()) { // Not found, maybe the DIE offset provided wasn't correct? // *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << " was not found." << endl; @@ -577,7 +584,7 @@ static dw_offset_t DumpCallback else { // See if the DIE is in this compile unit? - if (dumpInfo->die_offset < cu->GetNextCompileUnitOffset()) + if (cu && dumpInfo->die_offset < cu->GetNextCompileUnitOffset()) { // This DIE is in this compile unit! if (s->GetVerbose()) @@ -590,7 +597,14 @@ static dw_offset_t DumpCallback else { // Skip to the next compile unit as the DIE isn't in the current one! - return cu->GetNextCompileUnitOffset(); + if (cu) + { + return cu->GetNextCompileUnitOffset(); + } + else + { + return DW_INVALID_OFFSET; + } } } } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 856a7fa7a2ff..10b51ffe0a8a 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -88,9 +88,10 @@ DWARFDebugInfoEntry::Attributes::RemoveAttribute(dw_attr_t attr) bool DWARFDebugInfoEntry::Attributes::ExtractFormValueAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, DWARFFormValue &form_value) const { + form_value.SetCompileUnit(CompileUnitAtIndex(i)); form_value.SetForm(FormAtIndex(i)); lldb::offset_t offset = DIEOffsetAtIndex(i); - return form_value.ExtractValue(dwarf2Data->get_debug_info_data(), &offset, CompileUnitAtIndex(i)); + return form_value.ExtractValue(dwarf2Data->get_debug_info_data(), &offset); } uint64_t @@ -107,7 +108,7 @@ DWARFDebugInfoEntry::Attributes::FormValueAsUnsignedAtIndex(SymbolFileDWARF* dwa { DWARFFormValue form_value; if (ExtractFormValueAtIndex(dwarf2Data, i, form_value)) - return form_value.Reference(CompileUnitAtIndex(i)); + return form_value.Reference(); return fail_value; } @@ -190,7 +191,7 @@ DWARFDebugInfoEntry::FastExtract if (cu->GetVersion() <= 2) form_size = cu->GetAddressByteSize(); else - form_size = 4; // 4 bytes for DWARF 32, 8 bytes for DWARF 64, but we don't support DWARF64 yet + form_size = cu->IsDWARF64() ? 8 : 4; break; // 0 sized form @@ -212,7 +213,6 @@ DWARFDebugInfoEntry::FastExtract break; // 4 byte values - case DW_FORM_strp : case DW_FORM_data4 : case DW_FORM_ref4 : form_size = 4; @@ -237,11 +237,12 @@ DWARFDebugInfoEntry::FastExtract form = debug_info_data.GetULEB128 (&offset); break; + case DW_FORM_strp : case DW_FORM_sec_offset : - if (cu->GetAddressByteSize () == 4) - debug_info_data.GetU32 (offset_ptr); - else + if (cu->IsDWARF64 ()) debug_info_data.GetU64 (offset_ptr); + else + debug_info_data.GetU32 (offset_ptr); break; default: @@ -284,7 +285,6 @@ DWARFDebugInfoEntry::Extract const DWARFDataExtractor& debug_info_data = dwarf2Data->get_debug_info_data(); // const DWARFDataExtractor& debug_str_data = dwarf2Data->get_debug_str_data(); const uint32_t cu_end_offset = cu->GetNextCompileUnitOffset(); - const uint8_t cu_addr_size = cu->GetAddressByteSize(); lldb::offset_t offset = *offset_ptr; // if (offset >= cu_end_offset) // Log::Error("DIE at offset 0x%8.8x is beyond the end of the current compile unit (0x%8.8x)", m_offset, cu_end_offset); @@ -319,8 +319,8 @@ DWARFDebugInfoEntry::Extract if (isCompileUnitTag && ((attr == DW_AT_entry_pc) || (attr == DW_AT_low_pc))) { - DWARFFormValue form_value(form); - if (form_value.ExtractValue(debug_info_data, &offset, cu)) + DWARFFormValue form_value(cu, form); + if (form_value.ExtractValue(debug_info_data, &offset)) { if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc) ((DWARFCompileUnit*)cu)->SetBaseAddress(form_value.Unsigned()); @@ -348,13 +348,13 @@ DWARFDebugInfoEntry::Extract // Compile unit address sized values case DW_FORM_addr : - form_size = cu_addr_size; + form_size = cu->GetAddressByteSize(); break; case DW_FORM_ref_addr : if (cu->GetVersion() <= 2) - form_size = cu_addr_size; + form_size = cu->GetAddressByteSize(); else - form_size = 4; // 4 bytes for DWARF 32, 8 bytes for DWARF 64, but we don't support DWARF64 yet + form_size = cu->IsDWARF64() ? 8 : 4; break; // 0 sized form @@ -376,10 +376,6 @@ DWARFDebugInfoEntry::Extract break; // 4 byte values - case DW_FORM_strp : - form_size = 4; - break; - case DW_FORM_data4 : case DW_FORM_ref4 : form_size = 4; @@ -404,11 +400,12 @@ DWARFDebugInfoEntry::Extract form_is_indirect = true; break; + case DW_FORM_strp : case DW_FORM_sec_offset : - if (cu->GetAddressByteSize () == 4) - debug_info_data.GetU32 (offset_ptr); - else + if (cu->IsDWARF64 ()) debug_info_data.GetU64 (offset_ptr); + else + debug_info_data.GetU32 (offset_ptr); break; default: @@ -781,8 +778,8 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges for (i=0; iGetAttrAndFormByIndexUnchecked(i, attr, form); - DWARFFormValue form_value(form); - if (form_value.ExtractValue(debug_info_data, &offset, cu)) + DWARFFormValue form_value(cu, form); + if (form_value.ExtractValue(debug_info_data, &offset)) { switch (attr) { @@ -832,11 +829,11 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges break; case DW_AT_abstract_origin: - die_offsets.push_back(form_value.Reference(cu)); + die_offsets.push_back(form_value.Reference()); break; case DW_AT_specification: - die_offsets.push_back(form_value.Reference(cu)); + die_offsets.push_back(form_value.Reference()); break; case DW_AT_decl_file: @@ -1033,7 +1030,7 @@ DWARFDebugInfoEntry::DumpLocation const char *obj_file_name = NULL; ObjectFile *obj_file = dwarf2Data->GetObjectFile(); if (obj_file) - obj_file_name = obj_file->GetFileSpec().GetFilename().AsCString(); + obj_file_name = obj_file->GetFileSpec().GetFilename().AsCString(""); const char *die_name = GetName (dwarf2Data, cu); s.Printf ("0x%8.8x/0x%8.8x: %-30s (from %s in %s)", cu->GetOffset(), @@ -1077,9 +1074,9 @@ DWARFDebugInfoEntry::DumpAttribute s.Printf( "[%s", DW_FORM_value_to_name(form)); } - DWARFFormValue form_value(form); + DWARFFormValue form_value(cu, form); - if (!form_value.ExtractValue(debug_info_data, offset_ptr, cu)) + if (!form_value.ExtractValue(debug_info_data, offset_ptr)) return; if (show_form) @@ -1097,7 +1094,7 @@ DWARFDebugInfoEntry::DumpAttribute // Always dump form value if verbose is enabled if (verbose) { - form_value.Dump(s, debug_str_data, cu); + form_value.Dump(s, debug_str_data); } @@ -1130,7 +1127,7 @@ DWARFDebugInfoEntry::DumpAttribute if (blockData) { if (!verbose) - form_value.Dump(s, debug_str_data, cu); + form_value.Dump(s, debug_str_data); // Location description is inlined in data in the form value DWARFDataExtractor locationData(debug_info_data, (*offset_ptr) - form_value.Unsigned(), form_value.Unsigned()); @@ -1147,13 +1144,13 @@ DWARFDebugInfoEntry::DumpAttribute if (dwarf2Data) { if ( !verbose ) - form_value.Dump(s, debug_str_data, cu); + form_value.Dump(s, debug_str_data); DWARFLocationList::Dump(s, cu, dwarf2Data->get_debug_loc_data(), debug_loc_offset); } else { if ( !verbose ) - form_value.Dump(s, NULL, cu); + form_value.Dump(s, NULL); } } } @@ -1162,8 +1159,8 @@ DWARFDebugInfoEntry::DumpAttribute case DW_AT_abstract_origin: case DW_AT_specification: { - uint64_t abstract_die_offset = form_value.Reference(cu); - form_value.Dump(s, debug_str_data, cu); + uint64_t abstract_die_offset = form_value.Reference(); + form_value.Dump(s, debug_str_data); // *ostrm_ptr << HEX32 << abstract_die_offset << " ( "; if ( verbose ) s.PutCString(" ( "); GetName(dwarf2Data, cu, abstract_die_offset, s); @@ -1173,9 +1170,9 @@ DWARFDebugInfoEntry::DumpAttribute case DW_AT_type: { - uint64_t type_die_offset = form_value.Reference(cu); + uint64_t type_die_offset = form_value.Reference(); if (!verbose) - form_value.Dump(s, debug_str_data, cu); + form_value.Dump(s, debug_str_data); s.PutCString(" ( "); AppendTypeName(dwarf2Data, cu, type_die_offset, s); s.PutCString(" )"); @@ -1185,7 +1182,7 @@ DWARFDebugInfoEntry::DumpAttribute case DW_AT_ranges: { if ( !verbose ) - form_value.Dump(s, debug_str_data, cu); + form_value.Dump(s, debug_str_data); lldb::offset_t ranges_offset = form_value.Unsigned(); dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0; if (dwarf2Data) @@ -1195,7 +1192,7 @@ DWARFDebugInfoEntry::DumpAttribute default: if ( !verbose ) - form_value.Dump(s, debug_str_data, cu); + form_value.Dump(s, debug_str_data); break; } @@ -1226,13 +1223,12 @@ DWARFDebugInfoEntry::GetAttributes const DWARFDataExtractor& debug_info_data = dwarf2Data->get_debug_info_data(); if (fixed_form_sizes == NULL) - fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(cu->GetAddressByteSize()); + fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(cu->GetAddressByteSize(), cu->IsDWARF64()); const uint32_t num_attributes = abbrevDecl->NumAttributes(); uint32_t i; dw_attr_t attr; dw_form_t form; - DWARFFormValue form_value; for (i=0; iGetAttrAndFormByIndexUnchecked (i, attr, form); @@ -1259,11 +1255,11 @@ DWARFDebugInfoEntry::GetAttributes if ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin)) { - form_value.SetForm(form); - if (form_value.ExtractValue(debug_info_data, &offset, cu)) + DWARFFormValue form_value (cu, form); + if (form_value.ExtractValue(debug_info_data, &offset)) { const DWARFDebugInfoEntry* die = NULL; - dw_offset_t die_offset = form_value.Reference(cu); + dw_offset_t die_offset = form_value.Reference(); if (cu->ContainsDIEOffset(die_offset)) { die = const_cast(cu)->GetDIEPtr(die_offset); @@ -1331,8 +1327,9 @@ DWARFDebugInfoEntry::GetAttributeValue DWARFFormValue::SkipValue(abbrevDecl->GetFormByIndex(idx++), debug_info_data, &offset, cu); const dw_offset_t attr_offset = offset; + form_value.SetCompileUnit(cu); form_value.SetForm(abbrevDecl->GetFormByIndex(idx)); - if (form_value.ExtractValue(debug_info_data, &offset, cu)) + if (form_value.ExtractValue(debug_info_data, &offset)) { if (end_attr_offset_ptr) *end_attr_offset_ptr = offset; @@ -1423,7 +1420,7 @@ DWARFDebugInfoEntry::GetAttributeValueAsReference { DWARFFormValue form_value; if (GetAttributeValue(dwarf2Data, cu, attr, form_value)) - return form_value.Reference(cu); + return form_value.Reference(); return fail_value; } @@ -1590,7 +1587,7 @@ DWARFDebugInfoEntry::GetName if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value)) { DWARFCompileUnitSP cu_sp_ptr; - const DWARFDebugInfoEntry* die = const_cast(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(cu), &cu_sp_ptr); + const DWARFDebugInfoEntry* die = const_cast(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr); if (die) return die->GetName(dwarf2Data, cu_sp_ptr.get()); } @@ -1661,7 +1658,7 @@ DWARFDebugInfoEntry::GetPubname // The specification DIE may be in another compile unit so we need // to get a die and its compile unit. DWARFCompileUnitSP cu_sp_ptr; - const DWARFDebugInfoEntry* die = const_cast(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(cu), &cu_sp_ptr); + const DWARFDebugInfoEntry* die = const_cast(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr); if (die) return die->GetPubname(dwarf2Data, cu_sp_ptr.get()); } @@ -1798,7 +1795,7 @@ DWARFDebugInfoEntry::AppendTypeName DWARFFormValue form_value; if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_type, form_value)) { - uint64_t next_die_offset = form_value.Reference(cu); + uint64_t next_die_offset = form_value.Reference(); result = AppendTypeName(dwarf2Data, cu, next_die_offset, s); } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp index 6a2649463b54..11589aede708 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp @@ -418,12 +418,16 @@ DWARFDebugLine::ParsePrologue(const DWARFDataExtractor& debug_line_data, lldb::o const char * s; prologue->total_length = debug_line_data.GetDWARFInitialLength(offset_ptr); prologue->version = debug_line_data.GetU16(offset_ptr); - if (prologue->version < 2 || prologue->version > 3) + if (prologue->version < 2 || prologue->version > 4) return false; prologue->prologue_length = debug_line_data.GetDWARFOffset(offset_ptr); const lldb::offset_t end_prologue_offset = prologue->prologue_length + *offset_ptr; prologue->min_inst_length = debug_line_data.GetU8(offset_ptr); + if (prologue->version >= 4) + prologue->maximum_operations_per_instruction = debug_line_data.GetU8(offset_ptr); + else + prologue->maximum_operations_per_instruction = 1; prologue->default_is_stmt = debug_line_data.GetU8(offset_ptr); prologue->line_base = debug_line_data.GetU8(offset_ptr); prologue->line_range = debug_line_data.GetU8(offset_ptr); @@ -486,13 +490,16 @@ DWARFDebugLine::ParseSupportFiles (const lldb::ModuleSP &module_sp, (void)debug_line_data.GetDWARFInitialLength(&offset); const char * s; uint32_t version = debug_line_data.GetU16(&offset); - if (version < 2 || version > 3) + if (version < 2 || version > 4) return false; const dw_offset_t end_prologue_offset = debug_line_data.GetDWARFOffset(&offset) + offset; - // Skip instruction length, default is stmt, line base, line range and - // opcode base, and all opcode lengths + // Skip instruction length, default is stmt, line base, line range offset += 4; + // For DWARF4, skip maximum operations per instruction + if (version >= 4) + offset += 1; + // Skip opcode base, and all opcode lengths const uint8_t opcode_base = debug_line_data.GetU8(&offset); offset += opcode_base - 1; std::vector include_directories; @@ -650,7 +657,10 @@ DWARFDebugLine::ParseStatementTable // relocatable address. All of the other statement program opcodes // that affect the address register add a delta to it. This instruction // stores a relocatable value into it instead. - state.address = debug_line_data.GetAddress(offset_ptr); + if (arg_size == 4) + state.address = debug_line_data.GetU32(offset_ptr); + else // arg_size == 8 + state.address = debug_line_data.GetU64(offset_ptr); break; case DW_LNE_define_file: diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h index 0caaf596add5..7da0e76a22be 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h @@ -75,6 +75,7 @@ public: uint16_t version; // Version identifier for the statement information format. uint32_t prologue_length;// The number of bytes following the prologue_length field to the beginning of the first byte of the statement program itself. uint8_t min_inst_length;// The size in bytes of the smallest target machine instruction. Statement program opcodes that alter the address register first multiply their operands by this value. + uint8_t maximum_operations_per_instruction; // New in DWARF4. The maximum number of individual operations that may be encoded in an instruction. uint8_t default_is_stmt;// The initial value of theis_stmtregister. int8_t line_base; // This parameter affects the meaning of the special opcodes. See below. uint8_t line_range; // This parameter affects the meaning of the special opcodes. See below. diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp index 488e9820b6fa..8469b78d0dd5 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp @@ -87,7 +87,7 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data) DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx); - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize()); + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize(), cu->IsDWARF64()); bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index ab8e68ab5516..a8c550e9176f 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -96,36 +96,92 @@ g_form_sizes_addr8[] = 8, // 0x20 DW_FORM_ref_sig8 }; +// Difference with g_form_sizes_addr8: +// DW_FORM_strp and DW_FORM_sec_offset are 8 instead of 4 +static uint8_t +g_form_sizes_addr8_dwarf64[] = +{ + 0, // 0x00 unused + 8, // 0x01 DW_FORM_addr + 0, // 0x02 unused + 0, // 0x03 DW_FORM_block2 + 0, // 0x04 DW_FORM_block4 + 2, // 0x05 DW_FORM_data2 + 4, // 0x06 DW_FORM_data4 + 8, // 0x07 DW_FORM_data8 + 0, // 0x08 DW_FORM_string + 0, // 0x09 DW_FORM_block + 0, // 0x0a DW_FORM_block1 + 1, // 0x0b DW_FORM_data1 + 1, // 0x0c DW_FORM_flag + 0, // 0x0d DW_FORM_sdata + 8, // 0x0e DW_FORM_strp + 0, // 0x0f DW_FORM_udata + 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, // 0x11 DW_FORM_ref1 + 2, // 0x12 DW_FORM_ref2 + 4, // 0x13 DW_FORM_ref4 + 8, // 0x14 DW_FORM_ref8 + 0, // 0x15 DW_FORM_ref_udata + 0, // 0x16 DW_FORM_indirect + 8, // 0x17 DW_FORM_sec_offset + 0, // 0x18 DW_FORM_exprloc + 0, // 0x19 DW_FORM_flag_present + 0, // 0x1a + 0, // 0x1b + 0, // 0x1c + 0, // 0x1d + 0, // 0x1e + 0, // 0x1f + 8, // 0x20 DW_FORM_ref_sig8 +}; + const uint8_t * -DWARFFormValue::GetFixedFormSizesForAddressSize (uint8_t addr_size) +DWARFFormValue::GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64) { - switch (addr_size) - { - case 4: return g_form_sizes_addr4; - case 8: return g_form_sizes_addr8; + if (!is_dwarf64) { + switch (addr_size) + { + case 4: return g_form_sizes_addr4; + case 8: return g_form_sizes_addr8; + } + } else { + if (addr_size == 8) + return g_form_sizes_addr8_dwarf64; + // is_dwarf64 && addr_size == 4 : no provider does this. } return NULL; } -DWARFFormValue::DWARFFormValue(dw_form_t form) : +DWARFFormValue::DWARFFormValue() : + m_cu (NULL), + m_form(0), + m_value() +{ +} + +DWARFFormValue::DWARFFormValue(const DWARFCompileUnit* cu, dw_form_t form) : + m_cu (cu), m_form(form), m_value() { } bool -DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* offset_ptr, const DWARFCompileUnit* cu) +DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* offset_ptr) { bool indirect = false; bool is_block = false; m_value.data = NULL; + uint8_t ref_addr_size; // Read the value for the form into value and follow and DW_FORM_indirect instances we run into do { indirect = false; switch (m_form) { - case DW_FORM_addr: m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu)); break; + case DW_FORM_addr: assert(m_cu); + m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(m_cu)); break; case DW_FORM_block2: m_value.value.uval = data.GetU16(offset_ptr); is_block = true; break; case DW_FORM_block4: m_value.value.uval = data.GetU32(offset_ptr); is_block = true; break; case DW_FORM_data2: m_value.value.uval = data.GetU16(offset_ptr); break; @@ -142,15 +198,17 @@ DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* off case DW_FORM_data1: m_value.value.uval = data.GetU8(offset_ptr); break; case DW_FORM_flag: m_value.value.uval = data.GetU8(offset_ptr); break; case DW_FORM_sdata: m_value.value.sval = data.GetSLEB128(offset_ptr); break; - case DW_FORM_strp: m_value.value.uval = data.GetU32(offset_ptr); break; + case DW_FORM_strp: assert(m_cu); + m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4); break; // case DW_FORM_APPLE_db_str: case DW_FORM_udata: m_value.value.uval = data.GetULEB128(offset_ptr); break; - case DW_FORM_ref_addr: - if (cu->GetVersion() <= 2) - m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu)); - else - m_value.value.uval = data.GetU32(offset_ptr); // 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet - break; + case DW_FORM_ref_addr: assert(m_cu); + ref_addr_size = 4; + if (m_cu->GetVersion() <= 2) + ref_addr_size = m_cu->GetAddressByteSize(); + else + ref_addr_size = m_cu->IsDWARF64() ? 8 : 4; + m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size); break; case DW_FORM_ref1: m_value.value.uval = data.GetU8(offset_ptr); break; case DW_FORM_ref2: m_value.value.uval = data.GetU16(offset_ptr); break; case DW_FORM_ref4: m_value.value.uval = data.GetU32(offset_ptr); break; @@ -161,7 +219,8 @@ DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* off indirect = true; break; - case DW_FORM_sec_offset: m_value.value.uval = data.GetU32(offset_ptr); break; + case DW_FORM_sec_offset: assert(m_cu); + m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4); break; case DW_FORM_flag_present: m_value.value.uval = 1; break; case DW_FORM_ref_sig8: m_value.value.uval = data.GetU64(offset_ptr); break; default: @@ -183,14 +242,15 @@ DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* off } bool -DWARFFormValue::SkipValue(const DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu) const +DWARFFormValue::SkipValue(const DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr) const { - return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, cu); + return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_cu); } bool DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu) { + uint8_t ref_addr_size; switch (form) { // Blocks if inlined data that have a length field and the data bytes @@ -212,10 +272,13 @@ DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_d return true; case DW_FORM_ref_addr: + ref_addr_size = 4; + assert (cu); // CU must be valid for DW_FORM_ref_addr objects or we will get this wrong if (cu->GetVersion() <= 2) - *offset_ptr += DWARFCompileUnit::GetAddressByteSize(cu); + ref_addr_size = cu->GetAddressByteSize(); else - *offset_ptr += 4;// 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet + ref_addr_size = cu->IsDWARF64() ? 8 : 4; + *offset_ptr += ref_addr_size; return true; // 0 bytes values (implied from DW_FORM) @@ -237,11 +300,12 @@ DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_d // 32 bit for DWARF 32, 64 for DWARF 64 case DW_FORM_sec_offset: - *offset_ptr += 4; + case DW_FORM_strp: + assert(cu); + *offset_ptr += (cu->IsDWARF64() ? 8 : 4); return true; // 4 byte values - case DW_FORM_strp: case DW_FORM_data4: case DW_FORM_ref4: *offset_ptr += 4; @@ -278,7 +342,7 @@ DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_d void -DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data, const DWARFCompileUnit* cu) const +DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const { uint64_t uvalue = Unsigned(); bool cu_relative_offset = false; @@ -348,7 +412,8 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data, const case DW_FORM_ref_addr: { - if (cu->GetVersion() <= 2) + assert (m_cu); // CU must be valid for DW_FORM_ref_addr objects or we will get this wrong + if (m_cu->GetVersion() <= 2) s.Address(uvalue, sizeof (uint64_t) * 2); else s.Address(uvalue, 4 * 2);// 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet @@ -370,10 +435,11 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data, const if (cu_relative_offset) { + assert (m_cu); // CU must be valid for DW_FORM_ref forms that are compile unit relative or we will get this wrong if (verbose) s.PutCString(" => "); - s.Printf("{0x%8.8" PRIx64 "}", (uvalue + (cu ? cu->GetOffset() : 0))); + s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_cu->GetOffset()); } } @@ -388,7 +454,7 @@ DWARFFormValue::AsCString(const DWARFDataExtractor* debug_str_data_ptr) const } uint64_t -DWARFFormValue::Reference(const DWARFCompileUnit* cu) const +DWARFFormValue::Reference() const { uint64_t die_offset = m_value.value.uval; switch (m_form) @@ -398,7 +464,8 @@ DWARFFormValue::Reference(const DWARFCompileUnit* cu) const case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: - die_offset += (cu ? cu->GetOffset() : 0); + assert (m_cu); // CU must be valid for DW_FORM_ref forms that are compile unit relative or we will get this wrong + die_offset += m_cu->GetOffset(); break; default: @@ -429,32 +496,6 @@ DWARFFormValue::Reference (dw_offset_t base_offset) const return die_offset; } -//---------------------------------------------------------------------- -// Resolve any compile unit specific references so that we don't need -// the compile unit at a later time in order to work with the form -// value. -//---------------------------------------------------------------------- -bool -DWARFFormValue::ResolveCompileUnitReferences(const DWARFCompileUnit* cu) -{ - switch (m_form) - { - case DW_FORM_ref1: - case DW_FORM_ref2: - case DW_FORM_ref4: - case DW_FORM_ref8: - case DW_FORM_ref_udata: - m_value.value.uval += cu->GetOffset(); - m_form = DW_FORM_ref_addr; - return true; - break; - - default: - break; - } - - return false; -} const uint8_t* DWARFFormValue::BlockData() const @@ -496,7 +537,7 @@ DWARFFormValue::IsDataForm(const dw_form_t form) } int -DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const DWARFDataExtractor* debug_str_data_ptr) +DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFDataExtractor* debug_str_data_ptr) { dw_form_t a_form = a_value.Form(); dw_form_t b_form = b_value.Form(); @@ -577,8 +618,8 @@ DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_ case DW_FORM_ref8: case DW_FORM_ref_udata: { - uint64_t a = a_value.Reference(a_cu); - uint64_t b = b_value.Reference(b_cu); + uint64_t a = a_value.Reference(); + uint64_t b = b_value.Reference(); if (a < b) return -1; if (a > b) diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h index d6c580c7ab1b..392df26a088e 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h @@ -45,35 +45,34 @@ public: eValueTypeBlock }; - DWARFFormValue(dw_form_t form = 0); + DWARFFormValue(); + DWARFFormValue(const DWARFCompileUnit* cu, dw_form_t form); + const DWARFCompileUnit* GetCompileUnit () const { return m_cu; } + void SetCompileUnit (const DWARFCompileUnit* cu) { m_cu = cu; } dw_form_t Form() const { return m_form; } void SetForm(dw_form_t form) { m_form = form; } const ValueType& Value() const { return m_value; } - void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor* debug_str_data, const DWARFCompileUnit* cu) const; + void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor* debug_str_data) const; bool ExtractValue(const lldb_private::DWARFDataExtractor& data, - lldb::offset_t* offset_ptr, - const DWARFCompileUnit* cu); + lldb::offset_t* offset_ptr); bool IsInlinedCStr() const { return (m_value.data != NULL) && m_value.data == (const uint8_t*)m_value.value.cstr; } const uint8_t* BlockData() const; - uint64_t Reference(const DWARFCompileUnit* cu) const; + uint64_t Reference() const; uint64_t Reference (dw_offset_t offset) const; - bool ResolveCompileUnitReferences(const DWARFCompileUnit* cu); bool Boolean() const { return m_value.value.uval != 0; } uint64_t Unsigned() const { return m_value.value.uval; } void SetUnsigned(uint64_t uval) { m_value.value.uval = uval; } int64_t Signed() const { return m_value.value.sval; } void SetSigned(int64_t sval) { m_value.value.sval = sval; } const char* AsCString(const lldb_private::DWARFDataExtractor* debug_str_data_ptr) const; - bool SkipValue(const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu) const; + bool SkipValue(const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr) const; static bool SkipValue(const dw_form_t form, const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu); -// static bool TransferValue(dw_form_t form, const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu, BinaryStreamBuf& out_buff); -// static bool TransferValue(const DWARFFormValue& formValue, const DWARFCompileUnit* cu, BinaryStreamBuf& out_buff); -// static bool PutUnsigned(dw_form_t form, dw_offset_t offset, uint64_t value, BinaryStreamBuf& out_buff, const DWARFCompileUnit* cu, bool fixup_cu_relative_refs); static bool IsBlockForm(const dw_form_t form); static bool IsDataForm(const dw_form_t form); - static const uint8_t * GetFixedFormSizesForAddressSize (uint8_t addr_size); - static int Compare (const DWARFFormValue& a, const DWARFFormValue& b, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const lldb_private::DWARFDataExtractor* debug_str_data_ptr); + static const uint8_t * GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64); + static int Compare (const DWARFFormValue& a, const DWARFFormValue& b, const lldb_private::DWARFDataExtractor* debug_str_data_ptr); protected: + const DWARFCompileUnit* m_cu; // Compile unit for this form dw_form_t m_form; // Form for this value ValueType m_value; // Contains all data for the form }; diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h index ab0c37beeac9..f8a8cc60467d 100644 --- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h +++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h @@ -442,9 +442,9 @@ struct DWARFMappedHash for (size_t i=0; i 0) strm.PutCString (", "); - DWARFFormValue form_value (header_data.atoms[i].form); + DWARFFormValue form_value (NULL, header_data.atoms[i].form); switch (header_data.atoms[i].type) { case eAtomTypeDIEOffset: // DIE offset, check form for encoding diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 842260dbc3ba..b3a5476227f4 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1457,7 +1457,7 @@ SymbolFileDWARF::ParseTemplateDIE (DWARFCompileUnit* dwarf_cu, case DW_TAG_template_type_parameter: case DW_TAG_template_value_parameter: { - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize()); + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64()); DWARFDebugInfoEntry::Attributes attributes; const size_t num_attributes = die->GetAttributes (this, @@ -1486,7 +1486,7 @@ SymbolFileDWARF::ParseTemplateDIE (DWARFCompileUnit* dwarf_cu, case DW_AT_type: if (attributes.ExtractFormValueAtIndex(this, i, form_value)) { - const dw_offset_t type_die_offset = form_value.Reference(dwarf_cu); + const dw_offset_t type_die_offset = form_value.Reference(); lldb_type = ResolveTypeUID(type_die_offset); if (lldb_type) clang_type = lldb_type->GetClangForwardType(); @@ -1752,7 +1752,7 @@ SymbolFileDWARF::ParseChildMembers size_t count = 0; const DWARFDebugInfoEntry *die; - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize()); + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64()); uint32_t member_idx = 0; BitfieldInfo last_field_info; ModuleSP module = GetObjectFile()->GetModule(); @@ -1803,7 +1803,7 @@ SymbolFileDWARF::ParseChildMembers case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break; - case DW_AT_type: encoding_uid = form_value.Reference(dwarf_cu); break; + case DW_AT_type: encoding_uid = form_value.Reference(); break; case DW_AT_bit_offset: bit_offset = form_value.Unsigned(); break; case DW_AT_bit_size: bit_size = form_value.Unsigned(); break; case DW_AT_byte_size: byte_size = form_value.Unsigned(); break; @@ -2201,7 +2201,7 @@ SymbolFileDWARF::ParseChildMembers case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; - case DW_AT_type: encoding_uid = form_value.Reference(dwarf_cu); break; + case DW_AT_type: encoding_uid = form_value.Reference(); break; case DW_AT_data_member_location: if (form_value.BlockData()) { @@ -2990,7 +2990,7 @@ SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line, if (block_die != NULL) sc.block = block.FindBlockByID (MakeUserID(block_die->GetOffset())); - else + else if (function_die != NULL) sc.block = block.FindBlockByID (MakeUserID(function_die->GetOffset())); } } @@ -3033,7 +3033,7 @@ SymbolFileDWARF::Index () m_indexed = true; Timer scoped_timer (__PRETTY_FUNCTION__, "SymbolFileDWARF::Index (%s)", - GetObjectFile()->GetFileSpec().GetFilename().AsCString()); + GetObjectFile()->GetFileSpec().GetFilename().AsCString("")); DWARFDebugInfo* debug_info = DebugInfo(); if (debug_info) @@ -3197,13 +3197,13 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat if (m_apple_names_ap.get()) { const char *name_cstr = name.GetCString(); - const char *base_name_start; - const char *base_name_end = NULL; + llvm::StringRef basename; + llvm::StringRef context; - if (!CPPLanguageRuntime::StripNamespacesFromVariableName(name_cstr, base_name_start, base_name_end)) - base_name_start = name_cstr; + if (!CPPLanguageRuntime::ExtractContextAndIdentifier(name_cstr, context, basename)) + basename = name_cstr; - m_apple_names_ap->FindByName (base_name_start, die_offsets); + m_apple_names_ap->FindByName (basename.data(), die_offsets); } } else @@ -3402,7 +3402,7 @@ SymbolFileDWARF::ResolveFunction (DWARFCompileUnit *cu, break; } } - assert (die->Tag() == DW_TAG_subprogram); + assert (die && die->Tag() == DW_TAG_subprogram); if (GetFunction (cu, die, sc)) { Address addr; @@ -4231,7 +4231,7 @@ SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc, if (parent_die == NULL) return 0; - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize()); + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64()); size_t arg_idx = 0; const DWARFDebugInfoEntry *die; @@ -4266,7 +4266,7 @@ SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc, case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break; - case DW_AT_type: param_type_die_offset = form_value.Reference(dwarf_cu); break; + case DW_AT_type: param_type_die_offset = form_value.Reference(); break; case DW_AT_artificial: is_artificial = form_value.Boolean(); break; case DW_AT_location: // if (form_value.BlockData()) @@ -4409,7 +4409,7 @@ SymbolFileDWARF::ParseChildEnumerators size_t enumerators_added = 0; const DWARFDebugInfoEntry *die; - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize()); + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64()); for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) { @@ -4488,7 +4488,7 @@ SymbolFileDWARF::ParseChildArrayInfo return; const DWARFDebugInfoEntry *die; - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize()); + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64()); for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) { const dw_tag_t tag = die->Tag(); @@ -4929,7 +4929,7 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry { DEBUG_PRINTF ("resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n", MakeUserID(die->GetOffset()), - m_obj_file->GetFileSpec().GetFilename().AsCString(), + m_obj_file->GetFileSpec().GetFilename().AsCString(""), MakeUserID(type_die->GetOffset()), MakeUserID(type_cu->GetOffset())); @@ -5060,189 +5060,6 @@ SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugIn return true; } -// This function can be used when a DIE is found that is a forward declaration -// DIE and we want to try and find a type that has the complete definition. -// "cu" and "die" must be from this SymbolFileDWARF -TypeSP -SymbolFileDWARF::FindDefinitionTypeForDIE (DWARFCompileUnit* cu, - const DWARFDebugInfoEntry *die, - const ConstString &type_name) -{ - TypeSP type_sp; - -#if defined (LLDB_CONFIGURATION_DEBUG) - // You can't and shouldn't call this function with a compile unit from - // another SymbolFileDWARF instance. - assert (DebugInfo()->ContainsCompileUnit (cu)); -#endif - - if (cu == NULL || die == NULL || !type_name) - return type_sp; - - std::string qualified_name; - - Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION|DWARF_LOG_LOOKUPS)); - if (log) - { - die->GetQualifiedName(this, cu, qualified_name); - GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF::FindDefinitionTypeForDIE(die=0x%8.8x (%s), name='%s')", - die->GetOffset(), - qualified_name.c_str(), - type_name.GetCString()); - } - - DIEArray die_offsets; - - if (m_using_apple_tables) - { - if (m_apple_types_ap.get()) - { - const bool has_tag = m_apple_types_ap->GetHeader().header_data.ContainsAtom (DWARFMappedHash::eAtomTypeTag); - const bool has_qualified_name_hash = m_apple_types_ap->GetHeader().header_data.ContainsAtom (DWARFMappedHash::eAtomTypeQualNameHash); - if (has_tag && has_qualified_name_hash) - { - if (qualified_name.empty()) - die->GetQualifiedName(this, cu, qualified_name); - - const uint32_t qualified_name_hash = MappedHash::HashStringUsingDJB (qualified_name.c_str()); - if (log) - GetObjectFile()->GetModule()->LogMessage (log,"FindByNameAndTagAndQualifiedNameHash()"); - m_apple_types_ap->FindByNameAndTagAndQualifiedNameHash (type_name.GetCString(), die->Tag(), qualified_name_hash, die_offsets); - } - else if (has_tag) - { - if (log) - GetObjectFile()->GetModule()->LogMessage (log,"FindByNameAndTag()"); - m_apple_types_ap->FindByNameAndTag (type_name.GetCString(), die->Tag(), die_offsets); - } - else - { - m_apple_types_ap->FindByName (type_name.GetCString(), die_offsets); - } - } - } - else - { - if (!m_indexed) - Index (); - - m_type_index.Find (type_name, die_offsets); - } - - const size_t num_matches = die_offsets.size(); - - const dw_tag_t die_tag = die->Tag(); - - DWARFCompileUnit* type_cu = NULL; - const DWARFDebugInfoEntry* type_die = NULL; - if (num_matches) - { - DWARFDebugInfo* debug_info = DebugInfo(); - for (size_t i=0; iGetDIEPtrWithCompileUnitHint (die_offset, &type_cu); - - if (type_die) - { - bool try_resolving_type = false; - - // Don't try and resolve the DIE we are looking for with the DIE itself! - if (type_die != die) - { - const dw_tag_t type_die_tag = type_die->Tag(); - // Make sure the tags match - if (type_die_tag == die_tag) - { - // The tags match, lets try resolving this type - try_resolving_type = true; - } - else - { - // The tags don't match, but we need to watch our for a - // forward declaration for a struct and ("struct foo") - // ends up being a class ("class foo { ... };") or - // vice versa. - switch (type_die_tag) - { - case DW_TAG_class_type: - // We had a "class foo", see if we ended up with a "struct foo { ... };" - try_resolving_type = (die_tag == DW_TAG_structure_type); - break; - case DW_TAG_structure_type: - // We had a "struct foo", see if we ended up with a "class foo { ... };" - try_resolving_type = (die_tag == DW_TAG_class_type); - break; - default: - // Tags don't match, don't event try to resolve - // using this type whose name matches.... - break; - } - } - } - - if (try_resolving_type) - { - if (log) - { - std::string qualified_name; - type_die->GetQualifiedName(this, cu, qualified_name); - GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF::FindDefinitionTypeForDIE(die=0x%8.8x, name='%s') trying die=0x%8.8x (%s)", - die->GetOffset(), - type_name.GetCString(), - type_die->GetOffset(), - qualified_name.c_str()); - } - - // Make sure the decl contexts match all the way up - if (DIEDeclContextsMatch(cu, die, type_cu, type_die)) - { - Type *resolved_type = ResolveType (type_cu, type_die, false); - if (resolved_type && resolved_type != DIE_IS_BEING_PARSED) - { - DEBUG_PRINTF ("resolved 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ") from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n", - MakeUserID(die->GetOffset()), - MakeUserID(cu->GetOffset()), - m_obj_file->GetFileSpec().GetFilename().AsCString(), - MakeUserID(type_die->GetOffset()), - MakeUserID(type_cu->GetOffset())); - - m_die_to_type[die] = resolved_type; - type_sp = resolved_type->shared_from_this(); - break; - } - } - } - else - { - if (log) - { - std::string qualified_name; - type_die->GetQualifiedName(this, cu, qualified_name); - GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF::FindDefinitionTypeForDIE(die=0x%8.8x, name='%s') ignoring die=0x%8.8x (%s)", - die->GetOffset(), - type_name.GetCString(), - type_die->GetOffset(), - qualified_name.c_str()); - } - } - } - else - { - if (m_using_apple_tables) - { - GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", - die_offset, type_name.GetCString()); - } - } - - } - } - return type_sp; -} TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &dwarf_decl_ctx) @@ -5828,7 +5645,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, break; case DW_AT_byte_size: byte_size = form_value.Unsigned(); break; case DW_AT_encoding: encoding = form_value.Unsigned(); break; - case DW_AT_type: encoding_uid = form_value.Reference(dwarf_cu); break; + case DW_AT_type: encoding_uid = form_value.Reference(); break; default: case DW_AT_sibling: break; @@ -6403,7 +6220,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, type_name_cstr = form_value.AsCString(&get_debug_str_data()); type_name_const_str.SetCString(type_name_cstr); break; - case DW_AT_type: encoding_uid = form_value.Reference(dwarf_cu); break; + case DW_AT_type: encoding_uid = form_value.Reference(); break; case DW_AT_byte_size: byte_size = form_value.Unsigned(); break; case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; case DW_AT_declaration: break; //is_forward_declaration = form_value.Boolean(); break; @@ -6521,7 +6338,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, case DW_AT_linkage_name: case DW_AT_MIPS_linkage_name: break; // mangled = form_value.AsCString(&get_debug_str_data()); break; - case DW_AT_type: type_die_offset = form_value.Reference(dwarf_cu); break; + case DW_AT_type: type_die_offset = form_value.Reference(); break; case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break; case DW_AT_inline: is_inline = form_value.Boolean(); break; @@ -6541,15 +6358,15 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, break; case DW_AT_specification: - specification_die_offset = form_value.Reference(dwarf_cu); + specification_die_offset = form_value.Reference(); break; case DW_AT_abstract_origin: - abstract_origin_die_offset = form_value.Reference(dwarf_cu); + abstract_origin_die_offset = form_value.Reference(); break; case DW_AT_object_pointer: - object_pointer_die_offset = form_value.Reference(dwarf_cu); + object_pointer_die_offset = form_value.Reference(); break; case DW_AT_allocated: @@ -6985,7 +6802,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, type_name_const_str.SetCString(type_name_cstr); break; - case DW_AT_type: type_die_offset = form_value.Reference(dwarf_cu); break; + case DW_AT_type: type_die_offset = form_value.Reference(); break; case DW_AT_byte_size: break; // byte_size = form_value.Unsigned(); break; case DW_AT_byte_stride: byte_stride = form_value.Unsigned(); break; case DW_AT_bit_stride: bit_stride = form_value.Unsigned(); break; @@ -7019,17 +6836,26 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, byte_stride = element_type->GetByteSize(); ClangASTType array_element_type = element_type->GetClangForwardType(); uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride; - uint64_t num_elements = 0; - std::vector::const_reverse_iterator pos; - std::vector::const_reverse_iterator end = element_orders.rend(); - for (pos = element_orders.rbegin(); pos != end; ++pos) + if (element_orders.size() > 0) + { + uint64_t num_elements = 0; + std::vector::const_reverse_iterator pos; + std::vector::const_reverse_iterator end = element_orders.rend(); + for (pos = element_orders.rbegin(); pos != end; ++pos) + { + num_elements = *pos; + clang_type = ast.CreateArrayType (array_element_type, + num_elements, + is_vector); + array_element_type = clang_type; + array_element_bit_stride = num_elements ? + array_element_bit_stride * num_elements : + array_element_bit_stride; + } + } + else { - num_elements = *pos; - clang_type = ast.CreateArrayType (array_element_type, - num_elements, - is_vector); - array_element_type = clang_type; - array_element_bit_stride = num_elements ? array_element_bit_stride * num_elements : array_element_bit_stride; + clang_type = ast.CreateArrayType (array_element_type, 0, is_vector); } ConstString empty_name; type_sp.reset( new Type (MakeUserID(die->GetOffset()), @@ -7065,9 +6891,9 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, switch (attr) { case DW_AT_type: - type_die_offset = form_value.Reference(dwarf_cu); break; + type_die_offset = form_value.Reference(); break; case DW_AT_containing_type: - containing_type_die_offset = form_value.Reference(dwarf_cu); break; + containing_type_die_offset = form_value.Reference(); break; } } } @@ -7114,7 +6940,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, { symbol_context_scope = sc.comp_unit; } - else if (sc.function != NULL) + else if (sc.function != NULL && sc_parent_die) { symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset())); if (symbol_context_scope == NULL) @@ -7347,7 +7173,6 @@ SymbolFileDWARF::ParseVariableDIE const lldb::addr_t func_low_pc ) { - VariableSP var_sp (m_die_to_variable_sp[die]); if (var_sp) return var_sp; // Already been parsed! @@ -7380,6 +7205,7 @@ SymbolFileDWARF::ParseVariableDIE { dw_attr_t attr = attributes.AttributeAtIndex(i); DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(this, i, form_value)) { switch (attr) @@ -7390,7 +7216,7 @@ SymbolFileDWARF::ParseVariableDIE case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break; case DW_AT_linkage_name: case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break; - case DW_AT_type: type_uid = form_value.Reference(dwarf_cu); break; + case DW_AT_type: type_uid = form_value.Reference(); break; case DW_AT_external: is_external = form_value.Boolean(); break; case DW_AT_const_value: // If we have already found a DW_AT_location attribute, ignore this attribute. @@ -7409,7 +7235,7 @@ SymbolFileDWARF::ParseVariableDIE else if (DWARFFormValue::IsDataForm(form_value.Form())) { // Retrieve the value as a data expression. - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize()); + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), attributes.CompileUnitAtIndex(i)->IsDWARF64()); uint32_t data_offset = attributes.DIEOffsetAtIndex(i); uint32_t data_length = fixed_form_sizes[form_value.Form()]; if (data_length == 0) @@ -7417,7 +7243,7 @@ SymbolFileDWARF::ParseVariableDIE const uint8_t *data_pointer = form_value.BlockData(); if (data_pointer) { - data_length = form_value.Unsigned(); + form_value.Unsigned(); } else if (DWARFFormValue::IsDataForm(form_value.Form())) { @@ -7433,7 +7259,7 @@ SymbolFileDWARF::ParseVariableDIE // Retrieve the value as a string expression. if (form_value.Form() == DW_FORM_strp) { - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize()); + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), attributes.CompileUnitAtIndex(i)->IsDWARF64()); uint32_t data_offset = attributes.DIEOffsetAtIndex(i); uint32_t data_length = fixed_form_sizes[form_value.Form()]; location.CopyOpcodeData(module, debug_info_data, data_offset, data_length); @@ -7470,7 +7296,7 @@ SymbolFileDWARF::ParseVariableDIE { location.CopyOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length); assert (func_low_pc != LLDB_INVALID_ADDRESS); - location.SetLocationListSlide (func_low_pc - dwarf_cu->GetBaseAddress()); + location.SetLocationListSlide (func_low_pc - attributes.CompileUnitAtIndex(i)->GetBaseAddress()); } } } diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 178e5142d94b..230e1a5d3984 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -421,11 +421,6 @@ protected: const DWARFMappedHash::MemoryTable &memory_table, lldb_private::SymbolContextList& sc_list); - lldb::TypeSP FindDefinitionTypeForDIE ( - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *die, - const lldb_private::ConstString &type_name); - lldb::TypeSP FindDefinitionTypeForDWARFDeclContext ( const DWARFDeclContext &die_decl_ctx); diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index b8d56d3909e9..7e484bd8dc73 100644 --- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -146,7 +146,8 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& if (log && log->GetVerbose ()) { StreamString strm; - inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL); + const char *disassemble_format = "${frame.pc}: "; + inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL, NULL, NULL, disassemble_format); log->PutCString (strm.GetData()); } diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp index 32a21d2b8bb8..dbf37d8a4de0 100644 --- a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp +++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp @@ -23,6 +23,7 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/Target.h" #include "lldb/Target/UnwindAssembly.h" +#include "lldb/Utility/RegisterNumber.h" using namespace lldb; using namespace lldb_private; @@ -318,7 +319,8 @@ AssemblyParse_x86::nonvolatile_reg_p (int machine_regno) #define REX_W_DSTREG(opcode) ((opcode) & 0x1) // pushq %rbp [0x55] -bool AssemblyParse_x86::push_rbp_pattern_p () +bool +AssemblyParse_x86::push_rbp_pattern_p () { uint8_t *p = m_cur_insn_bytes; if (*p == 0x55) @@ -327,7 +329,8 @@ bool AssemblyParse_x86::push_rbp_pattern_p () } // pushq $0 ; the first instruction in start() [0x6a 0x00] -bool AssemblyParse_x86::push_0_pattern_p () +bool +AssemblyParse_x86::push_0_pattern_p () { uint8_t *p = m_cur_insn_bytes; if (*p == 0x6a && *(p + 1) == 0x0) @@ -337,7 +340,8 @@ bool AssemblyParse_x86::push_0_pattern_p () // pushq $0 // pushl $0 -bool AssemblyParse_x86::push_imm_pattern_p () +bool +AssemblyParse_x86::push_imm_pattern_p () { uint8_t *p = m_cur_insn_bytes; if (*p == 0x68 || *p == 0x6a) @@ -347,7 +351,8 @@ bool AssemblyParse_x86::push_imm_pattern_p () // movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5] // movl %esp, %ebp [0x8b 0xec] or [0x89 0xe5] -bool AssemblyParse_x86::mov_rsp_rbp_pattern_p () +bool +AssemblyParse_x86::mov_rsp_rbp_pattern_p () { uint8_t *p = m_cur_insn_bytes; if (m_wordsize == 8 && *p == 0x48) @@ -360,7 +365,8 @@ bool AssemblyParse_x86::mov_rsp_rbp_pattern_p () } // subq $0x20, %rsp -bool AssemblyParse_x86::sub_rsp_pattern_p (int& amount) +bool +AssemblyParse_x86::sub_rsp_pattern_p (int& amount) { uint8_t *p = m_cur_insn_bytes; if (m_wordsize == 8 && *p == 0x48) @@ -381,7 +387,8 @@ bool AssemblyParse_x86::sub_rsp_pattern_p (int& amount) } // addq $0x20, %rsp -bool AssemblyParse_x86::add_rsp_pattern_p (int& amount) +bool +AssemblyParse_x86::add_rsp_pattern_p (int& amount) { uint8_t *p = m_cur_insn_bytes; if (m_wordsize == 8 && *p == 0x48) @@ -403,7 +410,8 @@ bool AssemblyParse_x86::add_rsp_pattern_p (int& amount) // pushq %rbx // pushl %ebx -bool AssemblyParse_x86::push_reg_p (int& regno) +bool +AssemblyParse_x86::push_reg_p (int& regno) { uint8_t *p = m_cur_insn_bytes; int regno_prefix_bit = 0; @@ -423,7 +431,8 @@ bool AssemblyParse_x86::push_reg_p (int& regno) // popq %rbx // popl %ebx -bool AssemblyParse_x86::pop_reg_p (int& regno) +bool +AssemblyParse_x86::pop_reg_p (int& regno) { uint8_t *p = m_cur_insn_bytes; int regno_prefix_bit = 0; @@ -443,14 +452,16 @@ bool AssemblyParse_x86::pop_reg_p (int& regno) // popq %rbp [0x5d] // popl %ebp [0x5d] -bool AssemblyParse_x86::pop_rbp_pattern_p () +bool +AssemblyParse_x86::pop_rbp_pattern_p () { uint8_t *p = m_cur_insn_bytes; return (*p == 0x5d); } // call $0 [0xe8 0x0 0x0 0x0 0x0] -bool AssemblyParse_x86::call_next_insn_pattern_p () +bool +AssemblyParse_x86::call_next_insn_pattern_p () { uint8_t *p = m_cur_insn_bytes; return (*p == 0xe8) && (*(p+1) == 0x0) && (*(p+2) == 0x0) @@ -468,7 +479,8 @@ bool AssemblyParse_x86::call_next_insn_pattern_p () // the actual location. The positive value returned for the offset // is a convention used elsewhere for CFA offsets et al. -bool AssemblyParse_x86::mov_reg_to_local_stack_frame_p (int& regno, int& rbp_offset) +bool +AssemblyParse_x86::mov_reg_to_local_stack_frame_p (int& regno, int& rbp_offset) { uint8_t *p = m_cur_insn_bytes; int src_reg_prefix_bit = 0; @@ -602,7 +614,6 @@ bool AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan) { UnwindPlan::RowSP row(new UnwindPlan::Row); - int non_prologue_insn_count = 0; m_cur_insn = m_func_bounds.GetBaseAddress (); int current_func_text_offset = 0; int current_sp_bytes_offset_from_cfa = 0; @@ -638,20 +649,38 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan) *newrow = *row.get(); row.reset(newrow); + // Track which registers have been saved so far in the prologue. + // If we see another push of that register, it's not part of the prologue. + // The register numbers used here are the machine register #'s + // (i386_register_numbers, x86_64_register_numbers). + std::vector saved_registers(32, false); + const bool prefer_file_cache = true; + // Once the prologue has completed we'll save a copy of the unwind instructions + // If there is an epilogue in the middle of the function, after that epilogue we'll reinstate + // the unwind setup -- we assume that some code path jumps over the mid-function epilogue + + UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI + int prologue_completed_sp_bytes_offset_from_cfa; // The sp value before the epilogue started executed + std::vector prologue_completed_saved_registers; + Target *target = m_exe_ctx.GetTargetPtr(); - while (m_func_bounds.ContainsFileAddress (m_cur_insn) && non_prologue_insn_count < 10) + while (m_func_bounds.ContainsFileAddress (m_cur_insn)) { int stack_offset, insn_len; int machine_regno; // register numbers masked directly out of instructions uint32_t lldb_regno; // register numbers in lldb's eRegisterKindLLDB numbering scheme + bool in_epilogue = false; // we're in the middle of an epilogue sequence + bool row_updated = false; // The UnwindPlan::Row 'row' has been updated + if (!instruction_length (m_cur_insn, insn_len) || insn_len == 0 || insn_len > kMaxInstructionByteSize) { // An unrecognized/junk instruction break; } + if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes, insn_len, error) == static_cast(-1)) { @@ -661,216 +690,193 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan) if (push_rbp_pattern_p ()) { - row->SetOffset (current_func_text_offset + insn_len); current_sp_bytes_offset_from_cfa += m_wordsize; row->SetCFAOffset (current_sp_bytes_offset_from_cfa); UnwindPlan::Row::RegisterLocation regloc; regloc.SetAtCFAPlusOffset (-row->GetCFAOffset()); row->SetRegisterInfo (m_lldb_fp_regnum, regloc); - unwind_plan.AppendRow (row); - // Allocate a new Row, populate it with the existing Row contents. - newrow = new UnwindPlan::Row; - *newrow = *row.get(); - row.reset(newrow); - goto loopnext; + saved_registers[m_machine_fp_regnum] = true; + row_updated = true; } - if (mov_rsp_rbp_pattern_p ()) + else if (mov_rsp_rbp_pattern_p ()) { - row->SetOffset (current_func_text_offset + insn_len); row->SetCFARegister (m_lldb_fp_regnum); - unwind_plan.AppendRow (row); - // Allocate a new Row, populate it with the existing Row contents. - newrow = new UnwindPlan::Row; - *newrow = *row.get(); - row.reset(newrow); - goto loopnext; + row_updated = true; } // This is the start() function (or a pthread equivalent), it starts with a pushl $0x0 which puts the // saved pc value of 0 on the stack. In this case we want to pretend we didn't see a stack movement at all -- // normally the saved pc value is already on the stack by the time the function starts executing. - if (push_0_pattern_p ()) + else if (push_0_pattern_p ()) { - goto loopnext; } - if (push_reg_p (machine_regno)) + else if (push_reg_p (machine_regno)) { current_sp_bytes_offset_from_cfa += m_wordsize; - bool need_to_push_row = false; // the PUSH instruction has moved the stack pointer - if the CFA is set in terms of the stack pointer, // we need to add a new row of instructions. if (row->GetCFARegister() == m_lldb_sp_regnum) { - need_to_push_row = true; row->SetCFAOffset (current_sp_bytes_offset_from_cfa); + row_updated = true; } // record where non-volatile (callee-saved, spilled) registers are saved on the stack - if (nonvolatile_reg_p (machine_regno) && machine_regno_to_lldb_regno (machine_regno, lldb_regno)) + if (nonvolatile_reg_p (machine_regno) + && machine_regno_to_lldb_regno (machine_regno, lldb_regno) + && saved_registers[machine_regno] == false) { - need_to_push_row = true; UnwindPlan::Row::RegisterLocation regloc; regloc.SetAtCFAPlusOffset (-current_sp_bytes_offset_from_cfa); row->SetRegisterInfo (lldb_regno, regloc); + saved_registers[machine_regno] = true; + row_updated = true; } - if (need_to_push_row) - { - row->SetOffset (current_func_text_offset + insn_len); - unwind_plan.AppendRow (row); - // Allocate a new Row, populate it with the existing Row contents. - newrow = new UnwindPlan::Row; - *newrow = *row.get(); - row.reset(newrow); - } - goto loopnext; } - if (mov_reg_to_local_stack_frame_p (machine_regno, stack_offset) && nonvolatile_reg_p (machine_regno)) + else if (pop_reg_p (machine_regno)) { - if (machine_regno_to_lldb_regno (machine_regno, lldb_regno)) + current_sp_bytes_offset_from_cfa -= m_wordsize; + + if (nonvolatile_reg_p (machine_regno) + && machine_regno_to_lldb_regno (machine_regno, lldb_regno) + && saved_registers[machine_regno] == true) { - row->SetOffset (current_func_text_offset + insn_len); - UnwindPlan::Row::RegisterLocation regloc; + saved_registers[machine_regno] = false; + row->RemoveRegisterInfo (lldb_regno); - // stack_offset for 'movq %r15, -80(%rbp)' will be 80. - // In the Row, we want to express this as the offset from the CFA. If the frame base - // is rbp (like the above instruction), the CFA offset for rbp is probably 16. So we - // want to say that the value is stored at the CFA address - 96. - regloc.SetAtCFAPlusOffset (-(stack_offset + row->GetCFAOffset())); + if (machine_regno == m_machine_fp_regnum) + { + row->SetCFARegister (m_lldb_sp_regnum); + } - row->SetRegisterInfo (lldb_regno, regloc); - unwind_plan.AppendRow (row); - // Allocate a new Row, populate it with the existing Row contents. - newrow = new UnwindPlan::Row; - *newrow = *row.get(); - row.reset(newrow); - goto loopnext; + in_epilogue = true; + row_updated = true; } - } - if (sub_rsp_pattern_p (stack_offset)) - { - current_sp_bytes_offset_from_cfa += stack_offset; + // the POP instruction has moved the stack pointer - if the CFA is set in terms of the stack pointer, + // we need to add a new row of instructions. if (row->GetCFARegister() == m_lldb_sp_regnum) { - row->SetOffset (current_func_text_offset + insn_len); row->SetCFAOffset (current_sp_bytes_offset_from_cfa); - unwind_plan.AppendRow (row); - // Allocate a new Row, populate it with the existing Row contents. - newrow = new UnwindPlan::Row; - *newrow = *row.get(); - row.reset(newrow); + row_updated = true; } - goto loopnext; } - if (ret_pattern_p ()) + else if (mov_reg_to_local_stack_frame_p (machine_regno, stack_offset) + && nonvolatile_reg_p (machine_regno) + && machine_regno_to_lldb_regno (machine_regno, lldb_regno) + && saved_registers[machine_regno] == false) { - // we know where the end of the function is; set the limit on the PlanValidAddressRange - // in case our initial "high pc" value was overly large - // int original_size = m_func_bounds.GetByteSize(); - // int calculated_size = m_cur_insn.GetOffset() - m_func_bounds.GetBaseAddress().GetOffset() + insn_len + 1; - // m_func_bounds.SetByteSize (calculated_size); - // unwind_plan.SetPlanValidAddressRange (m_func_bounds); - break; - } + saved_registers[machine_regno] = true; - // FIXME recognize the i386 picbase setup instruction sequence, - // 0x1f16: call 0x1f1b ; main + 11 at /private/tmp/a.c:3 - // 0x1f1b: popl %eax - // and record the temporary stack movements if the CFA is not expressed in terms of ebp. + UnwindPlan::Row::RegisterLocation regloc; - non_prologue_insn_count++; -loopnext: - m_cur_insn.SetOffset (m_cur_insn.GetOffset() + insn_len); - current_func_text_offset += insn_len; - } + // stack_offset for 'movq %r15, -80(%rbp)' will be 80. + // In the Row, we want to express this as the offset from the CFA. If the frame base + // is rbp (like the above instruction), the CFA offset for rbp is probably 16. So we + // want to say that the value is stored at the CFA address - 96. + regloc.SetAtCFAPlusOffset (-(stack_offset + row->GetCFAOffset())); - // Now look at the byte at the end of the AddressRange for a limited attempt at describing the - // epilogue. We're looking for the sequence + row->SetRegisterInfo (lldb_regno, regloc); - // [ 0x5d ] mov %rbp, %rsp (aka pop %rbp) - // [ 0xc3 ] ret + row_updated = true; + } - // or + else if (sub_rsp_pattern_p (stack_offset)) + { + current_sp_bytes_offset_from_cfa += stack_offset; + if (row->GetCFARegister() == m_lldb_sp_regnum) + { + row->SetCFAOffset (current_sp_bytes_offset_from_cfa); + row_updated = true; + } + } - // [ 0x5d ] mov %rbp, %rsp (aka pop %rbp) - // [ 0xe9 xx xx xx xx ] jmp objc_retainAutoreleaseReturnValue (this is sometimes the final insn in the function) + else if (add_rsp_pattern_p (stack_offset)) + { + current_sp_bytes_offset_from_cfa -= stack_offset; + if (row->GetCFARegister() == m_lldb_sp_regnum) + { + row->SetCFAOffset (current_sp_bytes_offset_from_cfa); + row_updated = true; + } + in_epilogue = true; + } - // or + else if (ret_pattern_p () && prologue_completed_row.get()) + { + // Reinstate the saved prologue setup for any instructions + // that come after the ret instruction - // [ 0x5d ] mov %rbp, %rsp (aka pop %rbp) - // [ 0xc3 ] ret - // [ 0xe8 xx xx xx xx ] call __stack_chk_fail (this is sometimes the final insn in the function) + UnwindPlan::Row *newrow = new UnwindPlan::Row; + *newrow = *prologue_completed_row.get(); + row.reset (newrow); + current_sp_bytes_offset_from_cfa = prologue_completed_sp_bytes_offset_from_cfa; - // We want to add a Row describing how to unwind when we're stopped on the 'ret' instruction where the - // CFA is no longer defined in terms of rbp, but is now defined in terms of rsp like on function entry. - // (or the 'jmp' instruction in the second case) + saved_registers.clear(); + saved_registers.resize(prologue_completed_saved_registers.size(), false); + for (size_t i = 0; i < prologue_completed_saved_registers.size(); ++i) + { + saved_registers[i] = prologue_completed_saved_registers[i]; + } - uint64_t ret_insn_offset = LLDB_INVALID_ADDRESS; - Address end_of_fun(m_func_bounds.GetBaseAddress()); - end_of_fun.SetOffset (end_of_fun.GetOffset() + m_func_bounds.GetByteSize()); + in_epilogue = true; + row_updated = true; + } - if (m_func_bounds.GetByteSize() > 7) - { - uint8_t bytebuf[7]; - Address last_seven_bytes(end_of_fun); - last_seven_bytes.SetOffset (last_seven_bytes.GetOffset() - 7); - if (target->ReadMemory (last_seven_bytes, prefer_file_cache, bytebuf, 7, - error) != static_cast(-1)) + // call next instruction + // call 0 + // => pop %ebx + // This is used in i386 programs to get the PIC base address for finding global data + else if (call_next_insn_pattern_p ()) { - if (bytebuf[5] == 0x5d && bytebuf[6] == 0xc3) // mov & ret - { - ret_insn_offset = m_func_bounds.GetByteSize() - 1; - } - else if (bytebuf[1] == 0x5d && bytebuf[2] == 0xe9) // mov & jmp - { - // When the pc is sitting on the 'jmp' instruction, we have the same - // unwind state as if it was sitting on a 'ret' instruction. - ret_insn_offset = m_func_bounds.GetByteSize() - 5; - } - else if (bytebuf[0] == 0x5d && bytebuf[1] == 0xc3 && bytebuf[2] == 0xe8) // mov & ret & call + current_sp_bytes_offset_from_cfa += m_wordsize; + if (row->GetCFARegister() == m_lldb_sp_regnum) { - ret_insn_offset = m_func_bounds.GetByteSize() - 6; + row->SetCFAOffset (current_sp_bytes_offset_from_cfa); + row_updated = true; } } - } - else if (m_func_bounds.GetByteSize() > 2) - { - uint8_t bytebuf[2]; - Address last_two_bytes(end_of_fun); - last_two_bytes.SetOffset (last_two_bytes.GetOffset() - 2); - if (target->ReadMemory (last_two_bytes, prefer_file_cache, bytebuf, 2, - error) != static_cast(-1)) + + if (row_updated) { - if (bytebuf[0] == 0x5d && bytebuf[1] == 0xc3) // mov & ret + if (current_func_text_offset + insn_len < m_func_bounds.GetByteSize()) { - ret_insn_offset = m_func_bounds.GetByteSize() - 1; + row->SetOffset (current_func_text_offset + insn_len); + unwind_plan.AppendRow (row); + // Allocate a new Row, populate it with the existing Row contents. + newrow = new UnwindPlan::Row; + *newrow = *row.get(); + row.reset(newrow); } } - } - if (ret_insn_offset != LLDB_INVALID_ADDRESS) - { - // Create a fresh, empty Row and RegisterLocation - don't mention any other registers - UnwindPlan::RowSP epi_row(new UnwindPlan::Row); - UnwindPlan::Row::RegisterLocation epi_regloc; - - // When the ret instruction is about to be executed, here's our state - epi_row->SetOffset (ret_insn_offset); - epi_row->SetCFARegister (m_lldb_sp_regnum); - epi_row->SetCFAOffset (m_wordsize); + if (in_epilogue == false && row_updated) + { + // If we're not in an epilogue sequence, save the updated Row + UnwindPlan::Row *newrow = new UnwindPlan::Row; + *newrow = *row.get(); + prologue_completed_row.reset (newrow); - // caller's stack pointer value before the call insn is the CFA address - epi_regloc.SetIsCFAPlusOffset (0); - epi_row->SetRegisterInfo (m_lldb_sp_regnum, epi_regloc); + prologue_completed_saved_registers.clear(); + prologue_completed_saved_registers.resize(saved_registers.size(), false); + for (size_t i = 0; i < saved_registers.size(); ++i) + { + prologue_completed_saved_registers[i] = saved_registers[i]; + } + } - // saved instruction pointer can be found at CFA - wordsize - epi_regloc.SetAtCFAPlusOffset (-m_wordsize); - epi_row->SetRegisterInfo (m_lldb_ip_regnum, epi_regloc); + // We may change the sp value without adding a new Row necessarily -- keep + // track of it either way. + if (in_epilogue == false) + { + prologue_completed_sp_bytes_offset_from_cfa = current_sp_bytes_offset_from_cfa; + } - unwind_plan.AppendRow (epi_row); + m_cur_insn.SetOffset (m_cur_insn.GetOffset() + insn_len); + current_func_text_offset += insn_len; } unwind_plan.SetSourceName ("assembly insn profiling"); @@ -902,12 +908,20 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin if (cfa_reg != m_lldb_sp_regnum || first_row->GetCFAOffset() != m_wordsize) return false; + UnwindPlan::RowSP original_last_row = unwind_plan.GetRowForFunctionOffset (-1); + Target *target = m_exe_ctx.GetTargetPtr(); m_cur_insn = func.GetBaseAddress(); uint64_t offset = 0; int row_id = 1; bool unwind_plan_updated = false; UnwindPlan::RowSP row(new UnwindPlan::Row(*first_row)); + + // After a mid-function epilogue we will need to re-insert the original unwind rules + // so unwinds work for the remainder of the function. These aren't common with clang/gcc + // on x86 but it is possible. + bool reinstate_unwind_state = false; + while (func.ContainsFileAddress (m_cur_insn)) { int insn_len; @@ -930,10 +944,29 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin offset += insn_len; m_cur_insn.SetOffset(m_cur_insn.GetOffset() + insn_len); + if (reinstate_unwind_state) + { + // that was the last instruction of this function + if (func.ContainsFileAddress (m_cur_insn) == false) + continue; + + UnwindPlan::RowSP new_row(new UnwindPlan::Row()); + *new_row = *original_last_row; + new_row->SetOffset (offset); + unwind_plan.AppendRow (new_row); + row.reset (new UnwindPlan::Row()); + *row = *new_row; + reinstate_unwind_state = false; + unwind_plan_updated = true; + continue; + } + // If we already have one row for this instruction, we can continue. while (row_id < unwind_plan.GetRowCount() && unwind_plan.GetRowAtIndex (row_id)->GetOffset() <= offset) + { row_id++; + } UnwindPlan::RowSP original_row = unwind_plan.GetRowAtIndex (row_id - 1); if (original_row->GetOffset() == offset) { @@ -1032,6 +1065,11 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin unwind_plan_updated = true; continue; } + if (ret_pattern_p ()) + { + reinstate_unwind_state = true; + continue; + } } else if (cfa_reg == m_lldb_fp_regnum) { @@ -1053,6 +1091,7 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); unwind_plan.InsertRow (new_row); unwind_plan_updated = true; + reinstate_unwind_state = true; continue; } } @@ -1074,6 +1113,7 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin unwind_plan_source += " plus augmentation from assembly parsing"; unwind_plan.SetSourceName (unwind_plan_source.c_str()); unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); } return true; } @@ -1239,17 +1279,130 @@ UnwindAssembly_x86::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& func, Th bool UnwindAssembly_x86::AugmentUnwindPlanFromCallSite (AddressRange& func, Thread& thread, UnwindPlan& unwind_plan) { - ExecutionContext exe_ctx (thread.shared_from_this()); - AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func); - return asm_parse.augment_unwind_plan_from_call_site (func, unwind_plan); + bool do_augment_unwindplan = true; + + UnwindPlan::RowSP first_row = unwind_plan.GetRowForFunctionOffset (0); + UnwindPlan::RowSP last_row = unwind_plan.GetRowForFunctionOffset (-1); + + int wordsize = 8; + ProcessSP process_sp (thread.GetProcess()); + if (process_sp) + { + wordsize = process_sp->GetTarget().GetArchitecture().GetAddressByteSize(); + } + + RegisterNumber sp_regnum (thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); + RegisterNumber pc_regnum (thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + + // Does this UnwindPlan describe the prologue? I want to see that the CFA is set + // in terms of the stack pointer plus an offset, and I want to see that rip is + // retrieved at the CFA-wordsize. + // If there is no description of the prologue, don't try to augment this eh_frame + // unwinder code, fall back to assembly parsing instead. + + if (first_row->GetCFAType() != UnwindPlan::Row::CFAType::CFAIsRegisterPlusOffset + || RegisterNumber (thread, unwind_plan.GetRegisterKind(), first_row->GetCFARegister()) != sp_regnum + || first_row->GetCFAOffset() != wordsize) + { + return false; + } + UnwindPlan::Row::RegisterLocation first_row_pc_loc; + if (first_row->GetRegisterInfo (pc_regnum.GetAsKind (unwind_plan.GetRegisterKind()), first_row_pc_loc) == false + || first_row_pc_loc.IsAtCFAPlusOffset() == false + || first_row_pc_loc.GetOffset() != -wordsize) + { + return false; + } + + + // It looks like the prologue is described. + // Is the epilogue described? If it is, no need to do any augmentation. + + if (first_row != last_row && first_row->GetOffset() != last_row->GetOffset()) + { + // The first & last row have the same CFA register + // and the same CFA offset value + // and the CFA register is esp/rsp (the stack pointer). + + // We're checking that both of them have an unwind rule like "CFA=esp+4" or CFA+rsp+8". + + if (first_row->GetCFAType() == last_row->GetCFAType() + && first_row->GetCFARegister() == last_row->GetCFARegister() + && first_row->GetCFAOffset() == last_row->GetCFAOffset()) + { + // Get the register locations for eip/rip from the first & last rows. + // Are they both CFA plus an offset? Is it the same offset? + + UnwindPlan::Row::RegisterLocation last_row_pc_loc; + if (last_row->GetRegisterInfo (pc_regnum.GetAsKind (unwind_plan.GetRegisterKind()), last_row_pc_loc)) + { + if (last_row_pc_loc.IsAtCFAPlusOffset() + && first_row_pc_loc.GetOffset() == last_row_pc_loc.GetOffset()) + { + + // One last sanity check: Is the unwind rule for getting the caller pc value + // "deref the CFA-4" or "deref the CFA-8"? + + // If so, we have an UnwindPlan that already describes the epilogue and we don't need + // to modify it at all. + + if (first_row_pc_loc.GetOffset() == -wordsize) + { + do_augment_unwindplan = false; + } + } + } + } + } + + if (do_augment_unwindplan) + { + ExecutionContext exe_ctx (thread.shared_from_this()); + AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func); + return asm_parse.augment_unwind_plan_from_call_site (func, unwind_plan); + } + + return false; } bool UnwindAssembly_x86::GetFastUnwindPlan (AddressRange& func, Thread& thread, UnwindPlan &unwind_plan) { - ExecutionContext exe_ctx (thread.shared_from_this()); - AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func); - return asm_parse.get_fast_unwind_plan (func, unwind_plan); + // if prologue is + // 55 pushl %ebp + // 89 e5 movl %esp, %ebp + // or + // 55 pushq %rbp + // 48 89 e5 movq %rsp, %rbp + + // We should pull in the ABI architecture default unwind plan and return that + + llvm::SmallVector opcode_data; + + ProcessSP process_sp = thread.GetProcess(); + if (process_sp) + { + Target &target (process_sp->GetTarget()); + const bool prefer_file_cache = true; + Error error; + if (target.ReadMemory (func.GetBaseAddress (), prefer_file_cache, opcode_data.data(), + 4, error) == 4) + { + uint8_t i386_push_mov[] = {0x55, 0x89, 0xe5}; + uint8_t x86_64_push_mov[] = {0x55, 0x48, 0x89, 0xe5}; + + if (memcmp (opcode_data.data(), i386_push_mov, sizeof (i386_push_mov)) == 0 + || memcmp (opcode_data.data(), x86_64_push_mov, sizeof (x86_64_push_mov)) == 0) + { + ABISP abi_sp = process_sp->GetABI(); + if (abi_sp) + { + return abi_sp->CreateDefaultUnwindPlan (unwind_plan); + } + } + } + } + return false; } bool diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp index aae96bfa9a3b..d851ae792181 100644 --- a/source/Symbol/ClangASTContext.cpp +++ b/source/Symbol/ClangASTContext.cpp @@ -11,6 +11,7 @@ // C Includes // C++ Includes +#include #include // Other libraries and framework includes @@ -62,6 +63,7 @@ #include "lldb/Core/Flags.h" #include "lldb/Core/Log.h" #include "lldb/Core/RegularExpression.h" +#include "lldb/Core/ThreadSafeDenseMap.h" #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Expression/ASTDumper.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" @@ -79,13 +81,17 @@ using namespace lldb_private; using namespace llvm; using namespace clang; -typedef llvm::DenseMap ClangASTMap; +typedef lldb_private::ThreadSafeDenseMap ClangASTMap; static ClangASTMap & GetASTMap() { - static ClangASTMap g_map; - return g_map; + static ClangASTMap *g_map_ptr = nullptr; + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_map_ptr = new ClangASTMap(); // leaked on purpose to avoid spins + }); + return *g_map_ptr; } @@ -303,7 +309,7 @@ ClangASTContext::~ClangASTContext() { if (m_ast_ap.get()) { - GetASTMap().erase(m_ast_ap.get()); + GetASTMap().Erase(m_ast_ap.get()); } m_builtins_ap.reset(); @@ -409,7 +415,7 @@ ClangASTContext::getASTContext() m_ast_ap->getDiagnostics().setClient(getDiagnosticConsumer(), false); - GetASTMap().insert(std::make_pair(m_ast_ap.get(), this)); + GetASTMap().Insert(m_ast_ap.get(), this); } return m_ast_ap.get(); } @@ -417,7 +423,7 @@ ClangASTContext::getASTContext() ClangASTContext* ClangASTContext::GetASTContext (clang::ASTContext* ast) { - ClangASTContext *clang_ast = GetASTMap().lookup(ast); + ClangASTContext *clang_ast = GetASTMap().Lookup(ast); return clang_ast; } @@ -883,6 +889,13 @@ ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name break; case DW_ATE_float: + if (streq(type_name, "float") && QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) + return ClangASTType (ast, ast->FloatTy.getAsOpaquePtr()); + if (streq(type_name, "double") && QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) + return ClangASTType (ast, ast->DoubleTy.getAsOpaquePtr()); + if (streq(type_name, "long double") && QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy)) + return ClangASTType (ast, ast->LongDoubleTy.getAsOpaquePtr()); + // Fall back to not requring a name match if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) return ClangASTType (ast, ast->FloatTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) @@ -1119,6 +1132,16 @@ ClangASTContext::AreTypesSame (ClangASTType type1, return ast->hasSameType (type1_qual, type2_qual); } +ClangASTType +ClangASTContext::GetTypeForDecl (clang::NamedDecl *decl) +{ + if (clang::ObjCInterfaceDecl *interface_decl = llvm::dyn_cast(decl)) + return GetTypeForDecl(interface_decl); + if (clang::TagDecl *tag_decl = llvm::dyn_cast(decl)) + return GetTypeForDecl(tag_decl); + return ClangASTType(); +} + ClangASTType ClangASTContext::GetTypeForDecl (TagDecl *decl) @@ -1126,7 +1149,7 @@ ClangASTContext::GetTypeForDecl (TagDecl *decl) // No need to call the getASTContext() accessor (which can create the AST // if it isn't created yet, because we can't have created a decl in this // AST if our AST didn't already exist... - ASTContext *ast = m_ast_ap.get(); + ASTContext *ast = &decl->getASTContext(); if (ast) return ClangASTType (ast, ast->getTagDeclType(decl).getAsOpaquePtr()); return ClangASTType(); @@ -1138,7 +1161,7 @@ ClangASTContext::GetTypeForDecl (ObjCInterfaceDecl *decl) // No need to call the getASTContext() accessor (which can create the AST // if it isn't created yet, because we can't have created a decl in this // AST if our AST didn't already exist... - ASTContext *ast = m_ast_ap.get(); + ASTContext *ast = &decl->getASTContext(); if (ast) return ClangASTType (ast, ast->getObjCInterfaceType(decl).getAsOpaquePtr()); return ClangASTType(); @@ -1733,7 +1756,7 @@ ClangASTContext::CreateFunctionDeclaration (DeclContext *decl_ctx, DeclarationName (&ast->Idents.get(name)), function_clang_type.GetQualType(), nullptr, - (FunctionDecl::StorageClass)storage, + (clang::StorageClass)storage, is_inline, hasWrittenPrototype, isConstexprSpecified); @@ -1747,7 +1770,7 @@ ClangASTContext::CreateFunctionDeclaration (DeclContext *decl_ctx, DeclarationName (), function_clang_type.GetQualType(), nullptr, - (FunctionDecl::StorageClass)storage, + (clang::StorageClass)storage, is_inline, hasWrittenPrototype, isConstexprSpecified); @@ -1799,7 +1822,7 @@ ClangASTContext::CreateParameterDeclaration (const char *name, const ClangASTTyp name && name[0] ? &ast->Idents.get(name) : nullptr, param_type.GetQualType(), nullptr, - (VarDecl::StorageClass)storage, + (clang::StorageClass)storage, nullptr); } @@ -1849,7 +1872,23 @@ ClangASTContext::CreateArrayType (const ClangASTType &element_type, return ClangASTType(); } - +ClangASTType +ClangASTContext::GetOrCreateStructForIdentifier (const ConstString &type_name, + const std::initializer_list< std::pair < const char *, ClangASTType > >& type_fields, + bool packed) +{ + ClangASTType type; + if ((type = GetTypeForIdentifier(type_name)).IsValid()) + return type; + type = CreateRecordType(nullptr, lldb::eAccessPublic, type_name.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC); + type.StartTagDeclarationDefinition(); + for (const auto& field : type_fields) + type.AddFieldToRecordType(field.first, field.second, lldb::eAccessPublic, 0); + if (packed) + type.SetIsPacked(); + type.CompleteTagDeclarationDefinition(); + return type; +} #pragma mark Enumeration Types @@ -2067,7 +2106,7 @@ ClangASTContext::SetMetadata (clang::ASTContext *ast, ClangASTMetadata &metadata) { ClangExternalASTSourceCommon *external_source = - static_cast(ast->getExternalSource()); + ClangExternalASTSourceCommon::Lookup(ast->getExternalSource()); if (external_source) external_source->SetMetadata(object, metadata); @@ -2078,7 +2117,7 @@ ClangASTContext::GetMetadata (clang::ASTContext *ast, const void *object) { ClangExternalASTSourceCommon *external_source = - static_cast(ast->getExternalSource()); + ClangExternalASTSourceCommon::Lookup(ast->getExternalSource()); if (external_source && external_source->HasMetadata(object)) return external_source->GetMetadata(object); diff --git a/source/Symbol/ClangASTImporter.cpp b/source/Symbol/ClangASTImporter.cpp index 6579afb2f748..a925f808f858 100644 --- a/source/Symbol/ClangASTImporter.cpp +++ b/source/Symbol/ClangASTImporter.cpp @@ -86,7 +86,7 @@ ClangASTImporter::CopyDecl (clang::ASTContext *dst_ast, if (log) { - lldb::user_id_t user_id; + lldb::user_id_t user_id = LLDB_INVALID_UID; ClangASTMetadata *metadata = GetDeclMetadata(decl); if (metadata) user_id = metadata->GetUserID(); diff --git a/source/Symbol/ClangASTType.cpp b/source/Symbol/ClangASTType.cpp index a0878ae442c8..8b672fac4312 100644 --- a/source/Symbol/ClangASTType.cpp +++ b/source/Symbol/ClangASTType.cpp @@ -47,6 +47,7 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" +#include #include using namespace lldb; @@ -515,7 +516,7 @@ ClangASTType::GetNumberOfFunctionArguments () const } ClangASTType -ClangASTType::GetFunctionArgumentAtIndex (const size_t index) +ClangASTType::GetFunctionArgumentAtIndex (const size_t index) const { if (IsValid()) { @@ -1713,7 +1714,7 @@ ClangASTType::GetFunctionArgumentCount () const } ClangASTType -ClangASTType::GetFunctionArgumentTypeAtIndex (size_t idx) +ClangASTType::GetFunctionArgumentTypeAtIndex (size_t idx) const { if (IsValid()) { @@ -1741,6 +1742,199 @@ ClangASTType::GetFunctionReturnType () const return ClangASTType(); } +size_t +ClangASTType::GetNumMemberFunctions () const +{ + size_t num_functions = 0; + if (IsValid()) + { + clang::QualType qual_type(GetCanonicalQualType()); + switch (qual_type->getTypeClass()) { + case clang::Type::Record: + if (GetCompleteQualType (m_ast, qual_type)) + { + const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); + if (cxx_record_decl) + num_functions = std::distance(cxx_record_decl->method_begin(), cxx_record_decl->method_end()); + } + break; + + case clang::Type::ObjCObjectPointer: + if (GetCompleteType()) + { + const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); + if (class_interface_decl) + num_functions = std::distance(class_interface_decl->meth_begin(), class_interface_decl->meth_end()); + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType()) + { + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + if (class_interface_decl) + num_functions = std::distance(class_interface_decl->meth_begin(), class_interface_decl->meth_end()); + } + } + break; + + + case clang::Type::Typedef: + return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetNumMemberFunctions(); + + case clang::Type::Elaborated: + return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetNumMemberFunctions(); + + case clang::Type::Paren: + return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetNumMemberFunctions(); + + default: + break; + } + } + return num_functions; +} + +TypeMemberFunctionImpl +ClangASTType::GetMemberFunctionAtIndex (size_t idx) +{ + std::string name(""); + MemberFunctionKind kind(MemberFunctionKind::eMemberFunctionKindUnknown); + ClangASTType type{}; + clang::ObjCMethodDecl *method_decl(nullptr); + if (IsValid()) + { + clang::QualType qual_type(GetCanonicalQualType()); + switch (qual_type->getTypeClass()) { + case clang::Type::Record: + if (GetCompleteQualType (m_ast, qual_type)) + { + const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast(record_decl); + if (cxx_record_decl) + { + auto method_iter = cxx_record_decl->method_begin(); + auto method_end = cxx_record_decl->method_end(); + if (idx < static_cast(std::distance(method_iter, method_end))) + { + std::advance(method_iter, idx); + auto method_decl = method_iter->getCanonicalDecl(); + if (method_decl) + { + if (!method_decl->getName().empty()) + name.assign(method_decl->getName().data()); + else + name.clear(); + if (method_decl->isStatic()) + kind = lldb::eMemberFunctionKindStaticMethod; + else if (llvm::isa(method_decl)) + kind = lldb::eMemberFunctionKindConstructor; + else if (llvm::isa(method_decl)) + kind = lldb::eMemberFunctionKindDestructor; + else + kind = lldb::eMemberFunctionKindInstanceMethod; + type = ClangASTType(m_ast,method_decl->getType().getAsOpaquePtr()); + } + } + } + } + break; + + case clang::Type::ObjCObjectPointer: + if (GetCompleteType()) + { + const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); + if (class_interface_decl) + { + auto method_iter = class_interface_decl->meth_begin(); + auto method_end = class_interface_decl->meth_end(); + if (idx < static_cast(std::distance(method_iter, method_end))) + { + std::advance(method_iter, idx); + method_decl = method_iter->getCanonicalDecl(); + if (method_decl) + { + name = method_decl->getSelector().getAsString(); + if (method_decl->isClassMethod()) + kind = lldb::eMemberFunctionKindStaticMethod; + else + kind = lldb::eMemberFunctionKindInstanceMethod; + } + } + } + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType()) + { + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + if (class_interface_decl) + { + auto method_iter = class_interface_decl->meth_begin(); + auto method_end = class_interface_decl->meth_end(); + if (idx < static_cast(std::distance(method_iter, method_end))) + { + std::advance(method_iter, idx); + method_decl = method_iter->getCanonicalDecl(); + if (method_decl) + { + name = method_decl->getSelector().getAsString(); + if (method_decl->isClassMethod()) + kind = lldb::eMemberFunctionKindStaticMethod; + else + kind = lldb::eMemberFunctionKindInstanceMethod; + } + } + } + } + } + break; + + case clang::Type::Typedef: + return ClangASTType (m_ast, llvm::cast(qual_type)->getDecl()->getUnderlyingType()).GetMemberFunctionAtIndex(idx); + + case clang::Type::Elaborated: + return ClangASTType (m_ast, llvm::cast(qual_type)->getNamedType()).GetMemberFunctionAtIndex(idx); + + case clang::Type::Paren: + return ClangASTType (m_ast, llvm::cast(qual_type)->desugar()).GetMemberFunctionAtIndex(idx); + + default: + break; + } + } + + if (kind == eMemberFunctionKindUnknown) + return TypeMemberFunctionImpl(); + if (method_decl) + return TypeMemberFunctionImpl(method_decl, name, kind); + if (type) + return TypeMemberFunctionImpl(type, name, kind); + + return TypeMemberFunctionImpl(); +} ClangASTType ClangASTType::GetLValueReferenceType () const @@ -3448,7 +3642,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx, case clang::Type::IncompleteArray: if (ignore_array_bounds || idx_is_valid) { - const clang::ArrayType *array = llvm::cast(parent_qual_type.getTypePtr()); + const clang::ArrayType *array = GetQualType()->getAsArrayTypeUnsafe(); if (array) { ClangASTType element_type (m_ast, array->getElementType()); @@ -4752,6 +4946,17 @@ ClangASTType::BuildIndirectFields () } } +void +ClangASTType::SetIsPacked () +{ + clang::RecordDecl *record_decl = GetAsRecordDecl(); + + if (!record_decl) + return; + + record_decl->addAttr(clang::PackedAttr::CreateImplicit(*m_ast)); +} + clang::VarDecl * ClangASTType::AddVariableToRecordType (const char *name, const ClangASTType &var_type, @@ -5176,9 +5381,12 @@ ClangASTType::AddObjCClassProperty (const char *property_name, if (getter && metadata) ClangASTContext::SetMetadata(m_ast, getter, *metadata); - getter->setMethodParams(*m_ast, llvm::ArrayRef(), llvm::ArrayRef()); + if (getter) + { + getter->setMethodParams(*m_ast, llvm::ArrayRef(), llvm::ArrayRef()); - class_interface_decl->addDecl(getter); + class_interface_decl->addDecl(getter); + } } if (!setter_sel.isNull() && !class_interface_decl->lookupInstanceMethod(setter_sel)) @@ -5223,9 +5431,12 @@ ClangASTType::AddObjCClassProperty (const char *property_name, clang::SC_Auto, nullptr)); - setter->setMethodParams(*m_ast, llvm::ArrayRef(params), llvm::ArrayRef()); + if (setter) + { + setter->setMethodParams(*m_ast, llvm::ArrayRef(params), llvm::ArrayRef()); - class_interface_decl->addDecl(setter); + class_interface_decl->addDecl(setter); + } } return true; diff --git a/source/Symbol/ClangExternalASTSourceCommon.cpp b/source/Symbol/ClangExternalASTSourceCommon.cpp index 650d252a8fc3..79cc9a91355a 100644 --- a/source/Symbol/ClangExternalASTSourceCommon.cpp +++ b/source/Symbol/ClangExternalASTSourceCommon.cpp @@ -9,30 +9,52 @@ #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Core/Stream.h" +#include "lldb/Host/Mutex.h" using namespace lldb_private; -#define ClangExternalASTSourceCommon_MAGIC (0x00112233aabbccddull) - uint64_t g_TotalSizeOfMetadata = 0; -ClangExternalASTSourceCommon::ClangExternalASTSourceCommon() : clang::ExternalASTSource() +typedef llvm::DenseMap ASTSourceMap; + +static ASTSourceMap &GetSourceMap() +{ + static ASTSourceMap s_source_map; + return s_source_map; +} + +ClangExternalASTSourceCommon * +ClangExternalASTSourceCommon::Lookup(clang::ExternalASTSource *source) { - m_magic = ClangExternalASTSourceCommon_MAGIC; + ASTSourceMap &source_map = GetSourceMap(); + + ASTSourceMap::iterator iter = source_map.find(source); + if (iter != source_map.end()) + { + return iter->second; + } + else + { + return nullptr; + } +} + +ClangExternalASTSourceCommon::ClangExternalASTSourceCommon() : clang::ExternalASTSource() +{ g_TotalSizeOfMetadata += m_metadata.size(); + GetSourceMap()[this] = this; } ClangExternalASTSourceCommon::~ClangExternalASTSourceCommon() { + GetSourceMap().erase(this); g_TotalSizeOfMetadata -= m_metadata.size(); } ClangASTMetadata * ClangExternalASTSourceCommon::GetMetadata (const void *object) { - assert (m_magic == ClangExternalASTSourceCommon_MAGIC); - if (HasMetadata (object)) return &m_metadata[object]; else @@ -42,8 +64,6 @@ ClangExternalASTSourceCommon::GetMetadata (const void *object) void ClangExternalASTSourceCommon::SetMetadata (const void *object, ClangASTMetadata &metadata) { - assert (m_magic == ClangExternalASTSourceCommon_MAGIC); - uint64_t orig_size = m_metadata.size(); m_metadata[object] = metadata; uint64_t new_size = m_metadata.size(); @@ -53,8 +73,6 @@ ClangExternalASTSourceCommon::SetMetadata (const void *object, ClangASTMetadata bool ClangExternalASTSourceCommon::HasMetadata (const void *object) { - assert (m_magic == ClangExternalASTSourceCommon_MAGIC); - return m_metadata.find(object) != m_metadata.end(); } diff --git a/source/Symbol/CompactUnwindInfo.cpp b/source/Symbol/CompactUnwindInfo.cpp new file mode 100644 index 000000000000..8c6a2e7214c3 --- /dev/null +++ b/source/Symbol/CompactUnwindInfo.cpp @@ -0,0 +1,1215 @@ +//===-- CompactUnwindInfo.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +// C Includes +// C++ Includes +#include + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Symbol/CompactUnwindInfo.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +#include "llvm/Support/MathExtras.h" + +using namespace lldb; +using namespace lldb_private; + + +namespace lldb_private { + + // Constants from + + enum { + UNWIND_IS_NOT_FUNCTION_START = 0x80000000, + UNWIND_HAS_LSDA = 0x40000000, + UNWIND_PERSONALITY_MASK = 0x30000000, + }; + + enum { + UNWIND_X86_MODE_MASK = 0x0F000000, + UNWIND_X86_MODE_EBP_FRAME = 0x01000000, + UNWIND_X86_MODE_STACK_IMMD = 0x02000000, + UNWIND_X86_MODE_STACK_IND = 0x03000000, + UNWIND_X86_MODE_DWARF = 0x04000000, + + UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF, + UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000, + + UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000, + UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000, + UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00, + UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, + + UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF, + }; + + enum { + UNWIND_X86_REG_NONE = 0, + UNWIND_X86_REG_EBX = 1, + UNWIND_X86_REG_ECX = 2, + UNWIND_X86_REG_EDX = 3, + UNWIND_X86_REG_EDI = 4, + UNWIND_X86_REG_ESI = 5, + UNWIND_X86_REG_EBP = 6, + }; + enum { + UNWIND_X86_64_MODE_MASK = 0x0F000000, + UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000, + UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000, + UNWIND_X86_64_MODE_STACK_IND = 0x03000000, + UNWIND_X86_64_MODE_DWARF = 0x04000000, + + UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF, + UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000, + + UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000, + UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000, + UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00, + UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, + + UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF, + }; + + enum { + UNWIND_X86_64_REG_NONE = 0, + UNWIND_X86_64_REG_RBX = 1, + UNWIND_X86_64_REG_R12 = 2, + UNWIND_X86_64_REG_R13 = 3, + UNWIND_X86_64_REG_R14 = 4, + UNWIND_X86_64_REG_R15 = 5, + UNWIND_X86_64_REG_RBP = 6, + }; +}; + + +#ifndef UNWIND_SECOND_LEVEL_REGULAR +#define UNWIND_SECOND_LEVEL_REGULAR 2 +#endif + +#ifndef UNWIND_SECOND_LEVEL_COMPRESSED +#define UNWIND_SECOND_LEVEL_COMPRESSED 3 +#endif + +#ifndef UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET +#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF) +#endif + +#ifndef UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX +#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) ((entry >> 24) & 0xFF) +#endif + +#define EXTRACT_BITS(value, mask) \ + ( (value >> llvm::countTrailingZeros(static_cast(mask), llvm::ZB_Width)) & \ + (((1 << llvm::CountPopulation_32(static_cast(mask))))-1) ) + + + +//---------------------- +// constructor +//---------------------- + + +CompactUnwindInfo::CompactUnwindInfo(ObjectFile& objfile, SectionSP& section_sp) : + m_objfile (objfile), + m_section_sp (section_sp), + m_section_contents_if_encrypted (), + m_mutex (), + m_indexes (), + m_indexes_computed (eLazyBoolCalculate), + m_unwindinfo_data (), + m_unwindinfo_data_computed (false), + m_unwind_header () +{ + +} + +//---------------------- +// destructor +//---------------------- + +CompactUnwindInfo::~CompactUnwindInfo() +{ +} + +bool +CompactUnwindInfo::GetUnwindPlan (Target &target, Address addr, UnwindPlan& unwind_plan) +{ + if (!IsValid (target.GetProcessSP())) + { + return false; + } + FunctionInfo function_info; + if (GetCompactUnwindInfoForFunction (target, addr, function_info)) + { + // shortcut return for functions that have no compact unwind + if (function_info.encoding == 0) + return false; + + ArchSpec arch; + if (m_objfile.GetArchitecture (arch)) + { + + Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); + if (log && log->GetVerbose()) + { + StreamString strm; + addr.Dump (&strm, NULL, Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments, Address::DumpStyle::DumpStyleFileAddress, arch.GetAddressByteSize()); + log->Printf ("Got compact unwind encoding 0x%x for function %s", function_info.encoding, strm.GetData()); + } + + if (function_info.valid_range_offset_start != 0 && function_info.valid_range_offset_end != 0) + { + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + addr_t func_range_start_file_addr = + function_info.valid_range_offset_start + m_objfile.GetHeaderAddress().GetFileAddress(); + AddressRange func_range (func_range_start_file_addr, + function_info.valid_range_offset_end - function_info.valid_range_offset_start, + sl); + unwind_plan.SetPlanValidAddressRange (func_range); + } + } + + if (arch.GetTriple().getArch() == llvm::Triple::x86_64) + { + return CreateUnwindPlan_x86_64 (target, function_info, unwind_plan, addr); + } + if (arch.GetTriple().getArch() == llvm::Triple::x86) + { + return CreateUnwindPlan_i386 (target, function_info, unwind_plan, addr); + } + } + } + return false; +} + +bool +CompactUnwindInfo::IsValid (const ProcessSP &process_sp) +{ + if (m_section_sp.get() == nullptr) + return false; + + if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed) + return true; + + ScanIndex (process_sp); + + return m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed; +} + +void +CompactUnwindInfo::ScanIndex (const ProcessSP &process_sp) +{ + Mutex::Locker locker(m_mutex); + if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed) + return; + + // We can't read the index for some reason. + if (m_indexes_computed == eLazyBoolNo) + { + return; + } + + Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); + if (log) + m_objfile.GetModule()->LogMessage(log, "Reading compact unwind first-level indexes"); + + if (m_unwindinfo_data_computed == false) + { + if (m_section_sp->IsEncrypted()) + { + // Can't get section contents of a protected/encrypted section until we have a live + // process and can read them out of memory. + if (process_sp.get() == nullptr) + return; + m_section_contents_if_encrypted.reset (new DataBufferHeap (m_section_sp->GetByteSize(), 0)); + Error error; + if (process_sp->ReadMemory ( + m_section_sp->GetLoadBaseAddress (&process_sp->GetTarget()), + m_section_contents_if_encrypted->GetBytes(), + m_section_sp->GetByteSize(), error) == m_section_sp->GetByteSize() && error.Success()) + { + m_unwindinfo_data.SetAddressByteSize (process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); + m_unwindinfo_data.SetByteOrder (process_sp->GetTarget().GetArchitecture().GetByteOrder()); + m_unwindinfo_data.SetData (m_section_contents_if_encrypted, 0); + } + } + else + { + m_objfile.ReadSectionData (m_section_sp.get(), m_unwindinfo_data); + } + if (m_unwindinfo_data.GetByteSize() != m_section_sp->GetByteSize()) + return; + m_unwindinfo_data_computed = true; + } + + if (m_unwindinfo_data.GetByteSize() > 0) + { + offset_t offset = 0; + + // struct unwind_info_section_header + // { + // uint32_t version; // UNWIND_SECTION_VERSION + // uint32_t commonEncodingsArraySectionOffset; + // uint32_t commonEncodingsArrayCount; + // uint32_t personalityArraySectionOffset; + // uint32_t personalityArrayCount; + // uint32_t indexSectionOffset; + // uint32_t indexCount; + + m_unwind_header.version = m_unwindinfo_data.GetU32(&offset); + m_unwind_header.common_encodings_array_offset = m_unwindinfo_data.GetU32(&offset); + m_unwind_header.common_encodings_array_count = m_unwindinfo_data.GetU32(&offset); + m_unwind_header.personality_array_offset = m_unwindinfo_data.GetU32(&offset); + m_unwind_header.personality_array_count = m_unwindinfo_data.GetU32(&offset); + uint32_t indexSectionOffset = m_unwindinfo_data.GetU32(&offset); + + uint32_t indexCount = m_unwindinfo_data.GetU32(&offset); + + if (m_unwind_header.version != 1) + { + m_indexes_computed = eLazyBoolNo; + } + + // Parse the basic information from the indexes + // We wait to scan the second level page info until it's needed + + // struct unwind_info_section_header_index_entry + // { + // uint32_t functionOffset; + // uint32_t secondLevelPagesSectionOffset; + // uint32_t lsdaIndexArraySectionOffset; + // }; + + offset = indexSectionOffset; + for (uint32_t idx = 0; idx < indexCount; idx++) + { + uint32_t function_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset + uint32_t second_level_offset = m_unwindinfo_data.GetU32(&offset); // secondLevelPagesSectionOffset + uint32_t lsda_offset = m_unwindinfo_data.GetU32(&offset); // lsdaIndexArraySectionOffset + + if (second_level_offset > m_section_sp->GetByteSize() || lsda_offset > m_section_sp->GetByteSize()) + { + m_indexes_computed = eLazyBoolNo; + } + + UnwindIndex this_index; + this_index.function_offset = function_offset; // + this_index.second_level = second_level_offset; + this_index.lsda_array_start = lsda_offset; + + if (m_indexes.size() > 0) + { + m_indexes[m_indexes.size() - 1].lsda_array_end = lsda_offset; + } + + if (second_level_offset == 0) + { + this_index.sentinal_entry = true; + } + + m_indexes.push_back (this_index); + } + m_indexes_computed = eLazyBoolYes; + } + else + { + m_indexes_computed = eLazyBoolNo; + } +} + +uint32_t +CompactUnwindInfo::GetLSDAForFunctionOffset (uint32_t lsda_offset, uint32_t lsda_count, uint32_t function_offset) +{ + // struct unwind_info_section_header_lsda_index_entry + // { + // uint32_t functionOffset; + // uint32_t lsdaOffset; + // }; + + offset_t first_entry = lsda_offset; + uint32_t low = 0; + uint32_t high = lsda_count; + while (low < high) + { + uint32_t mid = (low + high) / 2; + offset_t offset = first_entry + (mid * 8); + uint32_t mid_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset + uint32_t mid_lsda_offset = m_unwindinfo_data.GetU32(&offset); // lsdaOffset + if (mid_func_offset == function_offset) + { + return mid_lsda_offset; + } + if (mid_func_offset < function_offset) + { + low = mid + 1; + } + else + { + high = mid; + } + } + return 0; +} + +lldb::offset_t +CompactUnwindInfo::BinarySearchRegularSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset, uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset) +{ + // typedef uint32_t compact_unwind_encoding_t; + // struct unwind_info_regular_second_level_entry + // { + // uint32_t functionOffset; + // compact_unwind_encoding_t encoding; + + offset_t first_entry = entry_page_offset; + + uint32_t low = 0; + uint32_t high = entry_count; + uint32_t last = high - 1; + while (low < high) + { + uint32_t mid = (low + high) / 2; + offset_t offset = first_entry + (mid * 8); + uint32_t mid_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset + uint32_t next_func_offset = 0; + if (mid < last) + { + offset = first_entry + ((mid + 1) * 8); + next_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset + } + if (mid_func_offset <= function_offset) + { + if (mid == last || (next_func_offset > function_offset)) + { + if (entry_func_start_offset) + *entry_func_start_offset = mid_func_offset; + if (mid != last && entry_func_end_offset) + *entry_func_end_offset = next_func_offset; + return first_entry + (mid * 8); + } + else + { + low = mid + 1; + } + } + else + { + high = mid; + } + } + return LLDB_INVALID_OFFSET; +} + +uint32_t +CompactUnwindInfo::BinarySearchCompressedSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset_to_find, uint32_t function_offset_base, uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset) +{ + offset_t first_entry = entry_page_offset; + + uint32_t low = 0; + uint32_t high = entry_count; + uint32_t last = high - 1; + while (low < high) + { + uint32_t mid = (low + high) / 2; + offset_t offset = first_entry + (mid * 4); + uint32_t entry = m_unwindinfo_data.GetU32(&offset); // entry + uint32_t mid_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (entry); + mid_func_offset += function_offset_base; + uint32_t next_func_offset = 0; + if (mid < last) + { + offset = first_entry + ((mid + 1) * 4); + uint32_t next_entry = m_unwindinfo_data.GetU32(&offset); // entry + next_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (next_entry); + next_func_offset += function_offset_base; + } + if (mid_func_offset <= function_offset_to_find) + { + if (mid == last || (next_func_offset > function_offset_to_find)) + { + if (entry_func_start_offset) + *entry_func_start_offset = mid_func_offset; + if (mid != last && entry_func_end_offset) + *entry_func_end_offset = next_func_offset; + return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX (entry); + } + else + { + low = mid + 1; + } + } + else + { + high = mid; + } + } + + return UINT32_MAX; +} + +bool +CompactUnwindInfo::GetCompactUnwindInfoForFunction (Target &target, Address address, FunctionInfo &unwind_info) +{ + unwind_info.encoding = 0; + unwind_info.lsda_address.Clear(); + unwind_info.personality_ptr_address.Clear(); + + if (!IsValid (target.GetProcessSP())) + return false; + + addr_t text_section_file_address = LLDB_INVALID_ADDRESS; + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + SectionSP text_sect = sl->FindSectionByType (eSectionTypeCode, true); + if (text_sect.get()) + { + text_section_file_address = text_sect->GetFileAddress(); + } + } + if (text_section_file_address == LLDB_INVALID_ADDRESS) + return false; + + addr_t function_offset = address.GetFileAddress() - m_objfile.GetHeaderAddress().GetFileAddress(); + + UnwindIndex key; + key.function_offset = function_offset; + + std::vector::const_iterator it; + it = std::lower_bound (m_indexes.begin(), m_indexes.end(), key); + if (it == m_indexes.end()) + { + return false; + } + + if (it->function_offset != key.function_offset) + { + if (it != m_indexes.begin()) + --it; + } + + if (it->sentinal_entry == true) + { + return false; + } + + auto next_it = it + 1; + if (next_it != m_indexes.begin()) + { + // initialize the function offset end range to be the start of the + // next index offset. If we find an entry which is at the end of + // the index table, this will establish the range end. + unwind_info.valid_range_offset_end = next_it->function_offset; + } + + offset_t second_page_offset = it->second_level; + offset_t lsda_array_start = it->lsda_array_start; + offset_t lsda_array_count = (it->lsda_array_end - it->lsda_array_start) / 8; + + offset_t offset = second_page_offset; + uint32_t kind = m_unwindinfo_data.GetU32(&offset); // UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED + + if (kind == UNWIND_SECOND_LEVEL_REGULAR) + { + // struct unwind_info_regular_second_level_page_header + // { + // uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR + // uint16_t entryPageOffset; + // uint16_t entryCount; + + // typedef uint32_t compact_unwind_encoding_t; + // struct unwind_info_regular_second_level_entry + // { + // uint32_t functionOffset; + // compact_unwind_encoding_t encoding; + + uint16_t entry_page_offset = m_unwindinfo_data.GetU16(&offset); // entryPageOffset + uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount + + offset_t entry_offset = BinarySearchRegularSecondPage (second_page_offset + entry_page_offset, entry_count, function_offset, &unwind_info.valid_range_offset_start, &unwind_info.valid_range_offset_end); + if (entry_offset == LLDB_INVALID_OFFSET) + { + return false; + } + entry_offset += 4; // skip over functionOffset + unwind_info.encoding = m_unwindinfo_data.GetU32(&entry_offset); // encoding + if (unwind_info.encoding & UNWIND_HAS_LSDA) + { + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + uint32_t lsda_offset = GetLSDAForFunctionOffset (lsda_array_start, lsda_array_count, function_offset); + addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); + unwind_info.lsda_address.ResolveAddressUsingFileSections (objfile_header_file_address + lsda_offset, sl); + } + } + if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) + { + uint32_t personality_index = EXTRACT_BITS (unwind_info.encoding, UNWIND_PERSONALITY_MASK); + + if (personality_index > 0) + { + personality_index--; + if (personality_index < m_unwind_header.personality_array_count) + { + offset_t offset = m_unwind_header.personality_array_offset; + offset += 4 * personality_index; + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset); + addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); + unwind_info.personality_ptr_address.ResolveAddressUsingFileSections (objfile_header_file_address + personality_offset, sl); + } + } + } + } + return true; + } + else if (kind == UNWIND_SECOND_LEVEL_COMPRESSED) + { + // struct unwind_info_compressed_second_level_page_header + // { + // uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED + // uint16_t entryPageOffset; // offset from this 2nd lvl page idx to array of entries + // // (an entry has a function offset and index into the encodings) + // // NB function offset from the entry in the compressed page + // // must be added to the index's functionOffset value. + // uint16_t entryCount; + // uint16_t encodingsPageOffset; // offset from this 2nd lvl page idx to array of encodings + // uint16_t encodingsCount; + + uint16_t entry_page_offset = m_unwindinfo_data.GetU16(&offset); // entryPageOffset + uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount + uint16_t encodings_page_offset = m_unwindinfo_data.GetU16(&offset); // encodingsPageOffset + uint16_t encodings_count = m_unwindinfo_data.GetU16(&offset); // encodingsCount + + uint32_t encoding_index = BinarySearchCompressedSecondPage (second_page_offset + entry_page_offset, entry_count, function_offset, it->function_offset, &unwind_info.valid_range_offset_start, &unwind_info.valid_range_offset_end); + if (encoding_index == UINT32_MAX || encoding_index >= encodings_count + m_unwind_header.common_encodings_array_count) + { + return false; + } + uint32_t encoding = 0; + if (encoding_index < m_unwind_header.common_encodings_array_count) + { + offset = m_unwind_header.common_encodings_array_offset + (encoding_index * sizeof (uint32_t)); + encoding = m_unwindinfo_data.GetU32(&offset); // encoding entry from the commonEncodingsArray + } + else + { + uint32_t page_specific_entry_index = encoding_index - m_unwind_header.common_encodings_array_count; + offset = second_page_offset + encodings_page_offset + (page_specific_entry_index * sizeof (uint32_t)); + encoding = m_unwindinfo_data.GetU32(&offset); // encoding entry from the page-specific encoding array + } + if (encoding == 0) + return false; + + unwind_info.encoding = encoding; + if (unwind_info.encoding & UNWIND_HAS_LSDA) + { + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + uint32_t lsda_offset = GetLSDAForFunctionOffset (lsda_array_start, lsda_array_count, function_offset); + addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); + unwind_info.lsda_address.ResolveAddressUsingFileSections (objfile_header_file_address + lsda_offset, sl); + } + } + if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) + { + uint32_t personality_index = EXTRACT_BITS (unwind_info.encoding, UNWIND_PERSONALITY_MASK); + + if (personality_index > 0) + { + personality_index--; + if (personality_index < m_unwind_header.personality_array_count) + { + offset_t offset = m_unwind_header.personality_array_offset; + offset += 4 * personality_index; + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset); + addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); + unwind_info.personality_ptr_address.ResolveAddressUsingFileSections (objfile_header_file_address + personality_offset, sl); + } + } + } + } + return true; + } + return false; +} + +enum x86_64_eh_regnum { + rax = 0, + rdx = 1, + rcx = 2, + rbx = 3, + rsi = 4, + rdi = 5, + rbp = 6, + rsp = 7, + r8 = 8, + r9 = 9, + r10 = 10, + r11 = 11, + r12 = 12, + r13 = 13, + r14 = 14, + r15 = 15, + rip = 16 // this is officially the Return Address register number, but close enough +}; + +// Convert the compact_unwind_info.h register numbering scheme +// to eRegisterKindGCC (eh_frame) register numbering scheme. +uint32_t +translate_to_eh_frame_regnum_x86_64 (uint32_t unwind_regno) +{ + switch (unwind_regno) + { + case UNWIND_X86_64_REG_RBX: + return x86_64_eh_regnum::rbx; + case UNWIND_X86_64_REG_R12: + return x86_64_eh_regnum::r12; + case UNWIND_X86_64_REG_R13: + return x86_64_eh_regnum::r13; + case UNWIND_X86_64_REG_R14: + return x86_64_eh_regnum::r14; + case UNWIND_X86_64_REG_R15: + return x86_64_eh_regnum::r15; + case UNWIND_X86_64_REG_RBP: + return x86_64_eh_regnum::rbp; + default: + return LLDB_INVALID_REGNUM; + } +} + +bool +CompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start) +{ + unwind_plan.SetSourceName ("compact unwind info"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolYes); + unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); + unwind_plan.SetRegisterKind (eRegisterKindGCC); + + unwind_plan.SetLSDAAddress (function_info.lsda_address); + unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address); + + UnwindPlan::RowSP row (new UnwindPlan::Row); + + const int wordsize = 8; + int mode = function_info.encoding & UNWIND_X86_64_MODE_MASK; + switch (mode) + { + case UNWIND_X86_64_MODE_RBP_FRAME: + { + row->SetCFARegister (translate_to_eh_frame_regnum_x86_64 (UNWIND_X86_64_REG_RBP)); + row->SetCFAOffset (2 * wordsize); + row->SetOffset (0); + row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rbp, wordsize * -2, true); + row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true); + row->SetRegisterLocationToIsCFAPlusOffset (x86_64_eh_regnum::rsp, 0, true); + + uint32_t saved_registers_offset = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_RBP_FRAME_OFFSET); + + uint32_t saved_registers_locations = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); + + saved_registers_offset += 2; + + for (int i = 0; i < 5; i++) + { + uint32_t regnum = saved_registers_locations & 0x7; + switch (regnum) + { + case UNWIND_X86_64_REG_NONE: + break; + case UNWIND_X86_64_REG_RBX: + case UNWIND_X86_64_REG_R12: + case UNWIND_X86_64_REG_R13: + case UNWIND_X86_64_REG_R14: + case UNWIND_X86_64_REG_R15: + row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_x86_64 (regnum), wordsize * -saved_registers_offset, true); + break; + } + saved_registers_offset--; + saved_registers_locations >>= 3; + } + unwind_plan.AppendRow (row); + return true; + } + break; + + case UNWIND_X86_64_MODE_STACK_IND: + { + // The clang in Xcode 6 is emitting incorrect compact unwind encodings for this + // style of unwind. It was fixed in llvm r217020. + return false; + } + break; + + case UNWIND_X86_64_MODE_STACK_IMMD: + { + uint32_t stack_size = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); + uint32_t register_count = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); + uint32_t permutation = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); + + if (mode == UNWIND_X86_64_MODE_STACK_IND && function_info.valid_range_offset_start != 0) + { + uint32_t stack_adjust = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); + + // offset into the function instructions; 0 == beginning of first instruction + uint32_t offset_to_subl_insn = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); + + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + ProcessSP process_sp = target.GetProcessSP(); + if (process_sp) + { + Address subl_payload_addr (function_info.valid_range_offset_start, sl); + subl_payload_addr.Slide (offset_to_subl_insn); + Error error; + uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory (subl_payload_addr.GetLoadAddress (&target), + 4, 0, error); + if (large_stack_size != 0 && error.Success ()) + { + // Got the large stack frame size correctly - use it + stack_size = large_stack_size + (stack_adjust * wordsize); + } + else + { + return false; + } + } + else + { + return false; + } + } + else + { + return false; + } + } + + row->SetCFARegister (x86_64_eh_regnum::rsp); + row->SetCFAOffset (stack_size * wordsize); + row->SetOffset (0); + row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true); + row->SetRegisterLocationToIsCFAPlusOffset (x86_64_eh_regnum::rsp, 0, true); + + if (register_count > 0) + { + + // We need to include (up to) 6 registers in 10 bits. + // That would be 18 bits if we just used 3 bits per reg to indicate + // the order they're saved on the stack. + // + // This is done with Lehmer code permutation, e.g. see + // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms + int permunreg[6]; + + // This decodes the variable-base number in the 10 bits + // and gives us the Lehmer code sequence which can then + // be decoded. + + switch (register_count) + { + case 6: + permunreg[0] = permutation/120; // 120 == 5! + permutation -= (permunreg[0]*120); + permunreg[1] = permutation/24; // 24 == 4! + permutation -= (permunreg[1]*24); + permunreg[2] = permutation/6; // 6 == 3! + permutation -= (permunreg[2]*6); + permunreg[3] = permutation/2; // 2 == 2! + permutation -= (permunreg[3]*2); + permunreg[4] = permutation; // 1 == 1! + permunreg[5] = 0; + break; + case 5: + permunreg[0] = permutation/120; + permutation -= (permunreg[0]*120); + permunreg[1] = permutation/24; + permutation -= (permunreg[1]*24); + permunreg[2] = permutation/6; + permutation -= (permunreg[2]*6); + permunreg[3] = permutation/2; + permutation -= (permunreg[3]*2); + permunreg[4] = permutation; + break; + case 4: + permunreg[0] = permutation/60; + permutation -= (permunreg[0]*60); + permunreg[1] = permutation/12; + permutation -= (permunreg[1]*12); + permunreg[2] = permutation/3; + permutation -= (permunreg[2]*3); + permunreg[3] = permutation; + break; + case 3: + permunreg[0] = permutation/20; + permutation -= (permunreg[0]*20); + permunreg[1] = permutation/4; + permutation -= (permunreg[1]*4); + permunreg[2] = permutation; + break; + case 2: + permunreg[0] = permutation/5; + permutation -= (permunreg[0]*5); + permunreg[1] = permutation; + break; + case 1: + permunreg[0] = permutation; + break; + } + + // Decode the Lehmer code for this permutation of + // the registers v. http://en.wikipedia.org/wiki/Lehmer_code + + int registers[6]; + bool used[7] = { false, false, false, false, false, false, false }; + for (uint32_t i = 0; i < register_count; i++) + { + int renum = 0; + for (int j = 1; j < 7; j++) + { + if (used[j] == false) + { + if (renum == permunreg[i]) + { + registers[i] = j; + used[j] = true; + break; + } + renum++; + } + } + } + + uint32_t saved_registers_offset = 1; + saved_registers_offset++; + + for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--) + { + switch (registers[i]) + { + case UNWIND_X86_64_REG_NONE: + break; + case UNWIND_X86_64_REG_RBX: + case UNWIND_X86_64_REG_R12: + case UNWIND_X86_64_REG_R13: + case UNWIND_X86_64_REG_R14: + case UNWIND_X86_64_REG_R15: + case UNWIND_X86_64_REG_RBP: + row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_x86_64 (registers[i]), wordsize * -saved_registers_offset, true); + break; + } + saved_registers_offset++; + } + } + unwind_plan.AppendRow (row); + return true; + } + break; + + case UNWIND_X86_64_MODE_DWARF: + { + return false; + } + break; + + case 0: + { + return false; + } + break; + } + return false; +} + +enum i386_eh_regnum { + eax = 0, + ecx = 1, + edx = 2, + ebx = 3, + ebp = 4, + esp = 5, + esi = 6, + edi = 7, + eip = 8 // this is officially the Return Address register number, but close enough +}; + +// Convert the compact_unwind_info.h register numbering scheme +// to eRegisterKindGCC (eh_frame) register numbering scheme. +uint32_t +translate_to_eh_frame_regnum_i386 (uint32_t unwind_regno) +{ + switch (unwind_regno) + { + case UNWIND_X86_REG_EBX: + return i386_eh_regnum::ebx; + case UNWIND_X86_REG_ECX: + return i386_eh_regnum::ecx; + case UNWIND_X86_REG_EDX: + return i386_eh_regnum::edx; + case UNWIND_X86_REG_EDI: + return i386_eh_regnum::edi; + case UNWIND_X86_REG_ESI: + return i386_eh_regnum::esi; + case UNWIND_X86_REG_EBP: + return i386_eh_regnum::ebp; + default: + return LLDB_INVALID_REGNUM; + } +} + + +bool +CompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start) +{ + unwind_plan.SetSourceName ("compact unwind info"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolYes); + unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); + unwind_plan.SetRegisterKind (eRegisterKindGCC); + + unwind_plan.SetLSDAAddress (function_info.lsda_address); + unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address); + + UnwindPlan::RowSP row (new UnwindPlan::Row); + + const int wordsize = 4; + int mode = function_info.encoding & UNWIND_X86_MODE_MASK; + switch (mode) + { + case UNWIND_X86_MODE_EBP_FRAME: + { + row->SetCFARegister (translate_to_eh_frame_regnum_i386 (UNWIND_X86_REG_EBP)); + row->SetCFAOffset (2 * wordsize); + row->SetOffset (0); + row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::ebp, wordsize * -2, true); + row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true); + row->SetRegisterLocationToIsCFAPlusOffset (i386_eh_regnum::esp, 0, true); + + uint32_t saved_registers_offset = EXTRACT_BITS (function_info.encoding, UNWIND_X86_EBP_FRAME_OFFSET); + + uint32_t saved_registers_locations = EXTRACT_BITS (function_info.encoding, UNWIND_X86_EBP_FRAME_REGISTERS); + + saved_registers_offset += 2; + + for (int i = 0; i < 5; i++) + { + uint32_t regnum = saved_registers_locations & 0x7; + switch (regnum) + { + case UNWIND_X86_REG_NONE: + break; + case UNWIND_X86_REG_EBX: + case UNWIND_X86_REG_ECX: + case UNWIND_X86_REG_EDX: + case UNWIND_X86_REG_EDI: + case UNWIND_X86_REG_ESI: + row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_i386 (regnum), wordsize * -saved_registers_offset, true); + break; + } + saved_registers_offset--; + saved_registers_locations >>= 3; + } + unwind_plan.AppendRow (row); + return true; + } + break; + + case UNWIND_X86_MODE_STACK_IND: + case UNWIND_X86_MODE_STACK_IMMD: + { + uint32_t stack_size = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); + uint32_t register_count = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT); + uint32_t permutation = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION); + + if (mode == UNWIND_X86_MODE_STACK_IND && function_info.valid_range_offset_start != 0) + { + uint32_t stack_adjust = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST); + + // offset into the function instructions; 0 == beginning of first instruction + uint32_t offset_to_subl_insn = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); + + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + ProcessSP process_sp = target.GetProcessSP(); + if (process_sp) + { + Address subl_payload_addr (function_info.valid_range_offset_start, sl); + subl_payload_addr.Slide (offset_to_subl_insn); + Error error; + uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory (subl_payload_addr.GetLoadAddress (&target), + 4, 0, error); + if (large_stack_size != 0 && error.Success ()) + { + // Got the large stack frame size correctly - use it + stack_size = large_stack_size + (stack_adjust * wordsize); + } + else + { + return false; + } + } + else + { + return false; + } + } + else + { + return false; + } + } + + row->SetCFARegister (i386_eh_regnum::esp); + row->SetCFAOffset (stack_size * wordsize); + row->SetOffset (0); + row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true); + row->SetRegisterLocationToIsCFAPlusOffset (i386_eh_regnum::esp, 0, true); + + if (register_count > 0) + { + + // We need to include (up to) 6 registers in 10 bits. + // That would be 18 bits if we just used 3 bits per reg to indicate + // the order they're saved on the stack. + // + // This is done with Lehmer code permutation, e.g. see + // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms + int permunreg[6]; + + // This decodes the variable-base number in the 10 bits + // and gives us the Lehmer code sequence which can then + // be decoded. + + switch (register_count) + { + case 6: + permunreg[0] = permutation/120; // 120 == 5! + permutation -= (permunreg[0]*120); + permunreg[1] = permutation/24; // 24 == 4! + permutation -= (permunreg[1]*24); + permunreg[2] = permutation/6; // 6 == 3! + permutation -= (permunreg[2]*6); + permunreg[3] = permutation/2; // 2 == 2! + permutation -= (permunreg[3]*2); + permunreg[4] = permutation; // 1 == 1! + permunreg[5] = 0; + break; + case 5: + permunreg[0] = permutation/120; + permutation -= (permunreg[0]*120); + permunreg[1] = permutation/24; + permutation -= (permunreg[1]*24); + permunreg[2] = permutation/6; + permutation -= (permunreg[2]*6); + permunreg[3] = permutation/2; + permutation -= (permunreg[3]*2); + permunreg[4] = permutation; + break; + case 4: + permunreg[0] = permutation/60; + permutation -= (permunreg[0]*60); + permunreg[1] = permutation/12; + permutation -= (permunreg[1]*12); + permunreg[2] = permutation/3; + permutation -= (permunreg[2]*3); + permunreg[3] = permutation; + break; + case 3: + permunreg[0] = permutation/20; + permutation -= (permunreg[0]*20); + permunreg[1] = permutation/4; + permutation -= (permunreg[1]*4); + permunreg[2] = permutation; + break; + case 2: + permunreg[0] = permutation/5; + permutation -= (permunreg[0]*5); + permunreg[1] = permutation; + break; + case 1: + permunreg[0] = permutation; + break; + } + + // Decode the Lehmer code for this permutation of + // the registers v. http://en.wikipedia.org/wiki/Lehmer_code + + int registers[6]; + bool used[7] = { false, false, false, false, false, false, false }; + for (uint32_t i = 0; i < register_count; i++) + { + int renum = 0; + for (int j = 1; j < 7; j++) + { + if (used[j] == false) + { + if (renum == permunreg[i]) + { + registers[i] = j; + used[j] = true; + break; + } + renum++; + } + } + } + + uint32_t saved_registers_offset = 1; + saved_registers_offset++; + + for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--) + { + switch (registers[i]) + { + case UNWIND_X86_REG_NONE: + break; + case UNWIND_X86_REG_EBX: + case UNWIND_X86_REG_ECX: + case UNWIND_X86_REG_EDX: + case UNWIND_X86_REG_EDI: + case UNWIND_X86_REG_ESI: + case UNWIND_X86_REG_EBP: + row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_i386 (registers[i]), wordsize * -saved_registers_offset, true); + break; + } + saved_registers_offset++; + } + } + + unwind_plan.AppendRow (row); + return true; + } + break; + + case UNWIND_X86_MODE_DWARF: + { + return false; + } + break; + } + return false; +} diff --git a/source/Symbol/CompileUnit.cpp b/source/Symbol/CompileUnit.cpp index f99ca53d9629..6483258ee678 100644 --- a/source/Symbol/CompileUnit.cpp +++ b/source/Symbol/CompileUnit.cpp @@ -325,18 +325,19 @@ CompileUnit::ResolveSymbolContext // when finding file indexes std::vector file_indexes; const bool full_match = (bool)file_spec.GetDirectory(); - bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *this, full_match); + const bool remove_backup_dots = true; + bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *this, full_match, remove_backup_dots); // If we are not looking for inlined functions and our file spec doesn't // match then we are done... if (file_spec_matches_cu_file_spec == false && check_inlines == false) return 0; - uint32_t file_idx = GetSupportFiles().FindFileIndex (1, file_spec, true); + uint32_t file_idx = GetSupportFiles().FindFileIndex (1, file_spec, true, remove_backup_dots); while (file_idx != UINT32_MAX) { file_indexes.push_back (file_idx); - file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec, true); + file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec, true, remove_backup_dots); } const size_t num_file_indexes = file_indexes.size(); diff --git a/source/Symbol/DWARFCallFrameInfo.cpp b/source/Symbol/DWARFCallFrameInfo.cpp index a9da631eb452..78d262307c24 100644 --- a/source/Symbol/DWARFCallFrameInfo.cpp +++ b/source/Symbol/DWARFCallFrameInfo.cpp @@ -218,20 +218,27 @@ DWARFCallFrameInfo::ParseCIE (const dw_offset_t cie_offset) // FDE, which is the address of a language-specific // data area (LSDA). The size of the LSDA pointer is // specified by the pointer encoding used. - m_cfi_data.GetU8(&offset); + cie_sp->lsda_addr_encoding = m_cfi_data.GetU8(&offset); break; case 'P': // Indicates the presence of two arguments in the - // Augmentation Data of the cie_sp-> The first argument + // Augmentation Data of the CIE. The first argument // is 1-byte and represents the pointer encoding // used for the second argument, which is the // address of a personality routine handler. The // size of the personality routine pointer is // specified by the pointer encoding used. + // + // The address of the personality function will + // be stored at this location. Pre-execution, it + // will be all zero's so don't read it until we're + // trying to do an unwind & the reloc has been + // resolved. { uint8_t arg_ptr_encoding = m_cfi_data.GetU8(&offset); - m_cfi_data.GetGNUEHPointer(&offset, arg_ptr_encoding, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS); + const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress(); + cie_sp->personality_loc = m_cfi_data.GetGNUEHPointer(&offset, arg_ptr_encoding, pc_rel_addr, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS); } break; @@ -449,11 +456,39 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr AddressRange range (range_base, m_objfile.GetAddressByteSize(), m_objfile.GetSectionList()); range.SetByteSize (range_len); + addr_t lsda_data_file_address = LLDB_INVALID_ADDRESS; + if (cie->augmentation[0] == 'z') { uint32_t aug_data_len = (uint32_t)m_cfi_data.GetULEB128(&offset); + if (aug_data_len != 0 && cie->lsda_addr_encoding != DW_EH_PE_omit) + { + offset_t saved_offset = offset; + lsda_data_file_address = m_cfi_data.GetGNUEHPointer(&offset, cie->lsda_addr_encoding, pc_rel_addr, text_addr, data_addr); + if (offset - saved_offset != aug_data_len) + { + // There is more in the augmentation region than we know how to process; + // don't read anything. + lsda_data_file_address = LLDB_INVALID_ADDRESS; + } + offset = saved_offset; + } offset += aug_data_len; } + Address lsda_data; + Address personality_function_ptr; + + if (lsda_data_file_address != LLDB_INVALID_ADDRESS && cie->personality_loc != LLDB_INVALID_ADDRESS) + { + m_objfile.GetModule()->ResolveFileAddress (lsda_data_file_address, lsda_data); + m_objfile.GetModule()->ResolveFileAddress (cie->personality_loc, personality_function_ptr); + } + + if (lsda_data.IsValid() && personality_function_ptr.IsValid()) + { + unwind_plan.SetLSDAAddress (lsda_data); + unwind_plan.SetPersonalityFunctionPtr (personality_function_ptr); + } uint32_t reg_num = 0; int32_t op_offset = 0; diff --git a/source/Symbol/Declaration.cpp b/source/Symbol/Declaration.cpp index 3943f02c5474..c72ca045b6c7 100644 --- a/source/Symbol/Declaration.cpp +++ b/source/Symbol/Declaration.cpp @@ -110,7 +110,7 @@ lldb_private::operator == (const Declaration &lhs, const Declaration &rhs) return lhs.GetFile() == rhs.GetFile(); #else if (lhs.GetLine () == rhs.GetLine ()) - return lhs.GetFile() == rhs.GetFile(); + return FileSpec::Equal(lhs.GetFile(),rhs.GetFile(), true, true); #endif return false; } diff --git a/source/Symbol/FuncUnwinders.cpp b/source/Symbol/FuncUnwinders.cpp index 95fc81747859..1eb73ee3649b 100644 --- a/source/Symbol/FuncUnwinders.cpp +++ b/source/Symbol/FuncUnwinders.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/Address.h" #include "lldb/Symbol/FuncUnwinders.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" +#include "lldb/Symbol/CompactUnwindInfo.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Symbol/UnwindTable.h" @@ -24,145 +25,212 @@ using namespace lldb; using namespace lldb_private; +//------------------------------------------------ +/// constructor +//------------------------------------------------ -FuncUnwinders::FuncUnwinders -( - UnwindTable& unwind_table, - AddressRange range -) : - m_unwind_table(unwind_table), - m_range(range), +FuncUnwinders::FuncUnwinders (UnwindTable& unwind_table, AddressRange range) : + m_unwind_table (unwind_table), + m_range (range), m_mutex (Mutex::eMutexTypeRecursive), - m_unwind_plan_call_site_sp (), - m_unwind_plan_non_call_site_sp (), + m_unwind_plan_assembly_sp (), + m_unwind_plan_eh_frame_sp (), + m_unwind_plan_eh_frame_augmented_sp (), + m_unwind_plan_compact_unwind (), m_unwind_plan_fast_sp (), m_unwind_plan_arch_default_sp (), - m_tried_unwind_at_call_site (false), - m_tried_unwind_at_non_call_site (false), + m_unwind_plan_arch_default_at_func_entry_sp (), + m_tried_unwind_plan_assembly (false), + m_tried_unwind_plan_eh_frame (false), + m_tried_unwind_plan_eh_frame_augmented (false), + m_tried_unwind_plan_compact_unwind (false), m_tried_unwind_fast (false), m_tried_unwind_arch_default (false), m_tried_unwind_arch_default_at_func_entry (false), - m_first_non_prologue_insn() + m_first_non_prologue_insn () { } -FuncUnwinders::~FuncUnwinders () +//------------------------------------------------ +/// destructor +//------------------------------------------------ + +FuncUnwinders::~FuncUnwinders () { } UnwindPlanSP -FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset) +FuncUnwinders::GetUnwindPlanAtCallSite (Target &target, int current_offset) { - // Lock the mutex to ensure we can always give out the most appropriate - // information. We want to make sure if someone requests a call site unwind - // plan, that they get one and don't run into a race condition where one - // thread has started to create the unwind plan and has put it into - // m_unwind_plan_call_site_sp, and have another thread enter this function - // and return the partially filled in m_unwind_plan_call_site_sp pointer. - // We also want to make sure that we lock out other unwind plans from - // being accessed until this one is done creating itself in case someone - // had some code like: - // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) - // if (best_unwind_plan == NULL) - // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) Mutex::Locker locker (m_mutex); - if (m_tried_unwind_at_call_site == false && m_unwind_plan_call_site_sp.get() == nullptr) + + UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, current_offset); + if (unwind_plan_sp.get() == nullptr) { - m_tried_unwind_at_call_site = true; - // We have cases (e.g. with _sigtramp on Mac OS X) where the hand-written eh_frame unwind info for a - // function does not cover the entire range of the function and so the FDE only lists a subset of the - // address range. If we try to look up the unwind info by the starting address of the function - // (i.e. m_range.GetBaseAddress()) we may not find the eh_frame FDE. We need to use the actual byte offset - // into the function when looking it up. - - if (m_range.GetBaseAddress().IsValid()) - { - Address current_pc (m_range.GetBaseAddress ()); - if (current_offset != -1) - current_pc.SetOffset (current_pc.GetOffset() + current_offset); + unwind_plan_sp = GetCompactUnwindUnwindPlan (target, current_offset); + } + + return unwind_plan_sp; +} - DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); - if (eh_frame) +UnwindPlanSP +FuncUnwinders::GetCompactUnwindUnwindPlan (Target &target, int current_offset) +{ + if (m_unwind_plan_compact_unwind.size() > 0) + return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact unwind plans for one func + if (m_tried_unwind_plan_compact_unwind) + return UnwindPlanSP(); + + Mutex::Locker lock (m_mutex); + m_tried_unwind_plan_compact_unwind = true; + if (m_range.GetBaseAddress().IsValid()) + { + Address current_pc (m_range.GetBaseAddress ()); + if (current_offset != -1) + current_pc.SetOffset (current_pc.GetOffset() + current_offset); + CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo(); + if (compact_unwind) + { + UnwindPlanSP unwind_plan_sp (new UnwindPlan (lldb::eRegisterKindGeneric)); + if (compact_unwind->GetUnwindPlan (target, current_pc, *unwind_plan_sp)) { - m_unwind_plan_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_call_site_sp)) - m_unwind_plan_call_site_sp.reset(); + m_unwind_plan_compact_unwind.push_back (unwind_plan_sp); + return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact unwind plans for one func } } } - return m_unwind_plan_call_site_sp; + return UnwindPlanSP(); } UnwindPlanSP -FuncUnwinders::GetUnwindPlanAtNonCallSite (Target& target, Thread& thread, int current_offset) +FuncUnwinders::GetEHFrameUnwindPlan (Target &target, int current_offset) { - // Lock the mutex to ensure we can always give out the most appropriate - // information. We want to make sure if someone requests an unwind - // plan, that they get one and don't run into a race condition where one - // thread has started to create the unwind plan and has put it into - // the unique pointer member variable, and have another thread enter this function - // and return the partially filled pointer contained in the unique pointer. - // We also want to make sure that we lock out other unwind plans from - // being accessed until this one is done creating itself in case someone - // had some code like: - // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) - // if (best_unwind_plan == NULL) - // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) - Mutex::Locker locker (m_mutex); - if (m_tried_unwind_at_non_call_site == false && m_unwind_plan_non_call_site_sp.get() == nullptr) + if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame) + return m_unwind_plan_eh_frame_sp; + + Mutex::Locker lock (m_mutex); + m_tried_unwind_plan_eh_frame = true; + if (m_range.GetBaseAddress().IsValid()) { - UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); - if (assembly_profiler_sp) + Address current_pc (m_range.GetBaseAddress ()); + if (current_offset != -1) + current_pc.SetOffset (current_pc.GetOffset() + current_offset); + DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); + if (eh_frame) { - if (target.GetArchitecture().GetCore() == ArchSpec::eCore_x86_32_i386 - || target.GetArchitecture().GetCore() == ArchSpec::eCore_x86_64_x86_64 - || target.GetArchitecture().GetCore() == ArchSpec::eCore_x86_64_x86_64h) + m_unwind_plan_eh_frame_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); + if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_eh_frame_sp)) + m_unwind_plan_eh_frame_sp.reset(); + } + } + return m_unwind_plan_eh_frame_sp; +} + +UnwindPlanSP +FuncUnwinders::GetEHFrameAugmentedUnwindPlan (Target &target, Thread &thread, int current_offset) +{ + if (m_unwind_plan_eh_frame_augmented_sp.get() || m_tried_unwind_plan_eh_frame_augmented) + return m_unwind_plan_eh_frame_augmented_sp; + + // Only supported on x86 architectures where we get eh_frame from the compiler that describes + // the prologue instructions perfectly, and sometimes the epilogue instructions too. + if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 + && target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 + && target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) + { + m_tried_unwind_plan_eh_frame_augmented = true; + return m_unwind_plan_eh_frame_augmented_sp; + } + + Mutex::Locker lock (m_mutex); + m_tried_unwind_plan_eh_frame_augmented = true; + + if (m_range.GetBaseAddress().IsValid()) + { + Address current_pc (m_range.GetBaseAddress ()); + if (current_offset != -1) + current_pc.SetOffset (current_pc.GetOffset() + current_offset); + DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); + if (eh_frame) + { + m_unwind_plan_eh_frame_augmented_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); + if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_eh_frame_augmented_sp)) { - // For 0th frame on i386 & x86_64, we fetch eh_frame and try using assembly profiler - // to augment it into asynchronous unwind table. - GetUnwindPlanAtCallSite(current_offset); - if (m_unwind_plan_call_site_sp) { - UnwindPlan* plan = new UnwindPlan (*m_unwind_plan_call_site_sp); - if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite (m_range, thread, *plan)) { - m_unwind_plan_non_call_site_sp.reset (plan); - return m_unwind_plan_non_call_site_sp; + m_unwind_plan_eh_frame_augmented_sp.reset(); + } + else + { + // Augment the eh_frame instructions with epilogue descriptions if necessary so the + // UnwindPlan can be used at any instruction in the function. + + UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); + if (assembly_profiler_sp) + { + if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite (m_range, thread, *m_unwind_plan_eh_frame_augmented_sp)) + { + m_unwind_plan_eh_frame_augmented_sp.reset(); } } + else + { + m_unwind_plan_eh_frame_augmented_sp.reset(); + } } + } + } + return m_unwind_plan_eh_frame_augmented_sp; +} + + +UnwindPlanSP +FuncUnwinders::GetAssemblyUnwindPlan (Target &target, Thread &thread, int current_offset) +{ + if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly) + return m_unwind_plan_assembly_sp; - m_unwind_plan_non_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_non_call_site_sp)) - m_unwind_plan_non_call_site_sp.reset(); + Mutex::Locker lock (m_mutex); + m_tried_unwind_plan_assembly = true; + + UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); + if (assembly_profiler_sp) + { + m_unwind_plan_assembly_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); + if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_assembly_sp)) + { + m_unwind_plan_assembly_sp.reset(); } } - return m_unwind_plan_non_call_site_sp; + return m_unwind_plan_assembly_sp; +} + + +UnwindPlanSP +FuncUnwinders::GetUnwindPlanAtNonCallSite (Target& target, Thread& thread, int current_offset) +{ + UnwindPlanSP non_call_site_unwindplan_sp = GetEHFrameAugmentedUnwindPlan (target, thread, current_offset); + if (non_call_site_unwindplan_sp.get() == nullptr) + { + non_call_site_unwindplan_sp = GetAssemblyUnwindPlan (target, thread, current_offset); + } + return non_call_site_unwindplan_sp; } UnwindPlanSP FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread) { - // Lock the mutex to ensure we can always give out the most appropriate - // information. We want to make sure if someone requests an unwind - // plan, that they get one and don't run into a race condition where one - // thread has started to create the unwind plan and has put it into - // the unique pointer member variable, and have another thread enter this function - // and return the partially filled pointer contained in the unique pointer. - // We also want to make sure that we lock out other unwind plans from - // being accessed until this one is done creating itself in case someone - // had some code like: - // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) - // if (best_unwind_plan == NULL) - // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) + if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast) + return m_unwind_plan_fast_sp; + Mutex::Locker locker (m_mutex); - if (m_tried_unwind_fast == false && m_unwind_plan_fast_sp.get() == nullptr) + m_tried_unwind_fast = true; + + UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); + if (assembly_profiler_sp) { - m_tried_unwind_fast = true; - UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); - if (assembly_profiler_sp) + m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); + if (!assembly_profiler_sp->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp)) { - m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (!assembly_profiler_sp->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp)) - m_unwind_plan_fast_sp.reset(); + m_unwind_plan_fast_sp.reset(); } } return m_unwind_plan_fast_sp; @@ -171,32 +239,23 @@ FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread) UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread) { - // Lock the mutex to ensure we can always give out the most appropriate - // information. We want to make sure if someone requests an unwind - // plan, that they get one and don't run into a race condition where one - // thread has started to create the unwind plan and has put it into - // the unique pointer member variable, and have another thread enter this function - // and return the partially filled pointer contained in the unique pointer. - // We also want to make sure that we lock out other unwind plans from - // being accessed until this one is done creating itself in case someone - // had some code like: - // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) - // if (best_unwind_plan == NULL) - // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) + if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default) + return m_unwind_plan_arch_default_sp; + Mutex::Locker locker (m_mutex); - if (m_tried_unwind_arch_default == false && m_unwind_plan_arch_default_sp.get() == nullptr) + m_tried_unwind_arch_default = true; + + Address current_pc; + ProcessSP process_sp (thread.CalculateProcess()); + if (process_sp) { - m_tried_unwind_arch_default = true; - Address current_pc; - ProcessSP process_sp (thread.CalculateProcess()); - if (process_sp) + ABI *abi = process_sp->GetABI().get(); + if (abi) { - ABI *abi = process_sp->GetABI().get(); - if (abi) + m_unwind_plan_arch_default_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); + if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp)) { - m_unwind_plan_arch_default_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (m_unwind_plan_arch_default_sp) - abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp); + m_unwind_plan_arch_default_sp.reset(); } } } @@ -207,32 +266,23 @@ FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread) UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry (Thread& thread) { - // Lock the mutex to ensure we can always give out the most appropriate - // information. We want to make sure if someone requests an unwind - // plan, that they get one and don't run into a race condition where one - // thread has started to create the unwind plan and has put it into - // the unique pointer member variable, and have another thread enter this function - // and return the partially filled pointer contained in the unique pointer. - // We also want to make sure that we lock out other unwind plans from - // being accessed until this one is done creating itself in case someone - // had some code like: - // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) - // if (best_unwind_plan == NULL) - // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) + if (m_unwind_plan_arch_default_at_func_entry_sp.get() || m_tried_unwind_arch_default_at_func_entry) + return m_unwind_plan_arch_default_at_func_entry_sp; + Mutex::Locker locker (m_mutex); - if (m_tried_unwind_arch_default_at_func_entry == false && m_unwind_plan_arch_default_at_func_entry_sp.get() == nullptr) + m_tried_unwind_arch_default_at_func_entry = true; + + Address current_pc; + ProcessSP process_sp (thread.CalculateProcess()); + if (process_sp) { - m_tried_unwind_arch_default_at_func_entry = true; - Address current_pc; - ProcessSP process_sp (thread.CalculateProcess()); - if (process_sp) + ABI *abi = process_sp->GetABI().get(); + if (abi) { - ABI *abi = process_sp->GetABI().get(); - if (abi) + m_unwind_plan_arch_default_at_func_entry_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); + if (!abi->CreateFunctionEntryUnwindPlan(*m_unwind_plan_arch_default_at_func_entry_sp)) { - m_unwind_plan_arch_default_at_func_entry_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (m_unwind_plan_arch_default_at_func_entry_sp) - abi->CreateFunctionEntryUnwindPlan(*m_unwind_plan_arch_default_at_func_entry_sp); + m_unwind_plan_arch_default_at_func_entry_sp.reset(); } } } @@ -246,9 +296,10 @@ FuncUnwinders::GetFirstNonPrologueInsn (Target& target) { if (m_first_non_prologue_insn.IsValid()) return m_first_non_prologue_insn; + + Mutex::Locker locker (m_mutex); ExecutionContext exe_ctx (target.shared_from_this(), false); UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); - if (assembly_profiler_sp) if (assembly_profiler_sp) assembly_profiler_sp->FirstNonPrologueInsn (m_range, exe_ctx, m_first_non_prologue_insn); return m_first_non_prologue_insn; @@ -260,16 +311,6 @@ FuncUnwinders::GetFunctionStartAddress () const return m_range.GetBaseAddress(); } -void -FuncUnwinders::InvalidateNonCallSiteUnwindPlan (lldb_private::Thread& thread) -{ - UnwindPlanSP arch_default = GetUnwindPlanArchitectureDefault (thread); - if (arch_default && m_tried_unwind_at_call_site) - { - m_unwind_plan_call_site_sp = arch_default; - } -} - lldb::UnwindAssemblySP FuncUnwinders::GetUnwindAssemblyProfiler () { @@ -281,3 +322,39 @@ FuncUnwinders::GetUnwindAssemblyProfiler () } return assembly_profiler_sp; } + +Address +FuncUnwinders::GetLSDAAddress (Target &target) +{ + Address lsda_addr; + + UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, -1); + if (unwind_plan_sp.get() == nullptr) + { + unwind_plan_sp = GetCompactUnwindUnwindPlan (target, -1); + } + if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) + { + lsda_addr = unwind_plan_sp->GetLSDAAddress(); + } + return lsda_addr; +} + + +Address +FuncUnwinders::GetPersonalityRoutinePtrAddress (Target &target) +{ + Address personality_addr; + + UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, -1); + if (unwind_plan_sp.get() == nullptr) + { + unwind_plan_sp = GetCompactUnwindUnwindPlan (target, -1); + } + if (unwind_plan_sp.get() && unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) + { + personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr(); + } + + return personality_addr; +} diff --git a/source/Symbol/LineTable.cpp b/source/Symbol/LineTable.cpp index 4b4e33b2b0e9..92b243d80a91 100644 --- a/source/Symbol/LineTable.cpp +++ b/source/Symbol/LineTable.cpp @@ -562,7 +562,6 @@ LineTable::LinkLineTable (const FileRangeMap &file_range_map) // Append the sequence since we just terminated the previous one line_table_ap->InsertSequence (&sequence); sequence.Clear(); - prev_entry_was_linked = false; } // Now link the current entry diff --git a/source/Symbol/ObjectFile.cpp b/source/Symbol/ObjectFile.cpp index 11b540071208..c24e83260d4d 100644 --- a/source/Symbol/ObjectFile.cpp +++ b/source/Symbol/ObjectFile.cpp @@ -371,6 +371,7 @@ ObjectFile::GetAddressClass (addr_t file_addr) case eSectionTypeDWARFAppleObjC: return eAddressClassDebug; case eSectionTypeEHFrame: + case eSectionTypeCompactUnwind: return eAddressClassRuntime; case eSectionTypeELFSymbolTable: case eSectionTypeELFDynamicSymbols: @@ -458,6 +459,9 @@ ObjectFile::CopyData (lldb::offset_t offset, size_t length, void *dst) const size_t ObjectFile::ReadSectionData (const Section *section, lldb::offset_t section_offset, void *dst, size_t dst_len) const { + assert(section); + section_offset *= section->GetTargetByteSize(); + // If some other objectfile owns this data, pass this to them. if (section->GetObjectFile() != this) return section->GetObjectFile()->ReadSectionData (section, section_offset, dst, dst_len); @@ -555,8 +559,6 @@ ObjectFile::MemoryMapSectionData (const Section *section, DataExtractor& section // The object file now contains a full mmap'ed copy of the object file data, so just use this return GetData(section->GetFileOffset(), section->GetFileSize(), section_data); } - section_data.Clear(); - return 0; } diff --git a/source/Symbol/Symbol.cpp b/source/Symbol/Symbol.cpp index 880519955277..b6ed94610b0a 100644 --- a/source/Symbol/Symbol.cpp +++ b/source/Symbol/Symbol.cpp @@ -626,7 +626,7 @@ Symbol::ResolveCallableAddress(Target &target) const Address func_so_addr; - bool is_indirect; + bool is_indirect = IsIndirect(); if (GetType() == eSymbolTypeReExported) { Symbol *reexported_symbol = ResolveReExportedSymbol(target); diff --git a/source/Symbol/SymbolContext.cpp b/source/Symbol/SymbolContext.cpp index 0e390dd08c5f..129f4def0067 100644 --- a/source/Symbol/SymbolContext.cpp +++ b/source/Symbol/SymbolContext.cpp @@ -128,7 +128,8 @@ SymbolContext::DumpStopContext const Address &addr, bool show_fullpaths, bool show_module, - bool show_inlined_frames + bool show_inlined_frames, + bool show_function_arguments ) const { bool dumped_something = false; @@ -146,7 +147,12 @@ SymbolContext::DumpStopContext { SymbolContext inline_parent_sc; Address inline_parent_addr; - if (function->GetMangled().GetName()) + if (show_function_arguments == false && function->GetMangled().GetName(Mangled::ePreferDemangledWithoutArguments)) + { + dumped_something = true; + function->GetMangled().GetName(Mangled::ePreferDemangledWithoutArguments).Dump(s); + } + else if (function->GetMangled().GetName()) { dumped_something = true; function->GetMangled().GetName().Dump(s); @@ -188,7 +194,7 @@ SymbolContext::DumpStopContext { s->EOL(); s->Indent(); - return inline_parent_sc.DumpStopContext (s, exe_scope, inline_parent_addr, show_fullpaths, show_module, show_inlined_frames); + return inline_parent_sc.DumpStopContext (s, exe_scope, inline_parent_addr, show_fullpaths, show_module, show_inlined_frames, show_function_arguments); } } else diff --git a/source/Symbol/Type.cpp b/source/Symbol/Type.cpp index 4eb538fb1352..42b76590aaea 100644 --- a/source/Symbol/Type.cpp +++ b/source/Symbol/Type.cpp @@ -31,6 +31,7 @@ #include "llvm/ADT/StringRef.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" using namespace lldb; using namespace lldb_private; @@ -1291,6 +1292,117 @@ TypeImpl::GetDescription (lldb_private::Stream &strm, return true; } +TypeMemberFunctionImpl& +TypeMemberFunctionImpl::operator = (const TypeMemberFunctionImpl& rhs) +{ + if (this != &rhs) + { + m_type = rhs.m_type; + m_objc_method_decl = rhs.m_objc_method_decl; + m_name = rhs.m_name; + m_kind = rhs.m_kind; + } + return *this; +} + +bool +TypeMemberFunctionImpl::IsValid () +{ + return m_type.IsValid() && m_kind != lldb::eMemberFunctionKindUnknown; +} + +ConstString +TypeMemberFunctionImpl::GetName () const +{ + return m_name; +} + +ClangASTType +TypeMemberFunctionImpl::GetType () const +{ + return m_type; +} + +lldb::MemberFunctionKind +TypeMemberFunctionImpl::GetKind () const +{ + return m_kind; +} + +std::string +TypeMemberFunctionImpl::GetPrintableTypeName () +{ + if (m_type) + return m_type.GetTypeName().AsCString(""); + if (m_objc_method_decl) + { + if (m_objc_method_decl->getClassInterface()) + { + return m_objc_method_decl->getClassInterface()->getName(); + } + } + return ""; +} + +bool +TypeMemberFunctionImpl::GetDescription (Stream& stream) +{ + switch (m_kind) { + case lldb::eMemberFunctionKindUnknown: + return false; + case lldb::eMemberFunctionKindConstructor: + stream.Printf("constructor for %s", GetPrintableTypeName().c_str()); + break; + case lldb::eMemberFunctionKindDestructor: + stream.Printf("destructor for %s", GetPrintableTypeName().c_str()); + break; + case lldb::eMemberFunctionKindInstanceMethod: + stream.Printf("instance method %s of type %s", + m_name.AsCString(), + GetPrintableTypeName().c_str()); + break; + case lldb::eMemberFunctionKindStaticMethod: + stream.Printf("static method %s of type %s", + m_name.AsCString(), + GetPrintableTypeName().c_str()); + break; + } + return true; +} + +ClangASTType +TypeMemberFunctionImpl::GetReturnType () const +{ + if (m_type) + return m_type.GetFunctionReturnType(); + if (m_objc_method_decl) + return ClangASTType(&m_objc_method_decl->getASTContext(),m_objc_method_decl->getReturnType().getAsOpaquePtr()); + return ClangASTType(); +} + +size_t +TypeMemberFunctionImpl::GetNumArguments () const +{ + if (m_type) + return m_type.GetNumberOfFunctionArguments(); + if (m_objc_method_decl) + return m_objc_method_decl->param_size(); + return 0; +} + +ClangASTType +TypeMemberFunctionImpl::GetArgumentAtIndex (size_t idx) const +{ + if (m_type) + return m_type.GetFunctionArgumentAtIndex (idx); + if (m_objc_method_decl) + { + if (idx < m_objc_method_decl->param_size()) + return ClangASTType(&m_objc_method_decl->getASTContext(), m_objc_method_decl->parameters()[idx]->getOriginalType().getAsOpaquePtr()); + } + return ClangASTType(); +} + TypeEnumMemberImpl::TypeEnumMemberImpl (const clang::EnumConstantDecl* enum_member_decl, const lldb_private::ClangASTType& integer_type) : m_integer_type_sp(), diff --git a/source/Symbol/UnwindPlan.cpp b/source/Symbol/UnwindPlan.cpp index ff0468e314d8..87d0f49421c5 100644 --- a/source/Symbol/UnwindPlan.cpp +++ b/source/Symbol/UnwindPlan.cpp @@ -153,6 +153,7 @@ UnwindPlan::Row::RegisterLocation::Dump (Stream &s, const UnwindPlan* unwind_pla void UnwindPlan::Row::Clear () { + m_cfa_type = CFAIsRegisterPlusOffset; m_offset = 0; m_cfa_reg_num = LLDB_INVALID_REGNUM; m_cfa_offset = 0; @@ -167,7 +168,7 @@ UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, if (base_addr != LLDB_INVALID_ADDRESS) s.Printf ("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset()); else - s.Printf ("0x%8.8" PRIx64 ": CFA=", GetOffset()); + s.Printf ("%4" PRId64 ": CFA=", GetOffset()); if (reg_info) s.Printf ("%s", reg_info->name); @@ -189,10 +190,11 @@ UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, } UnwindPlan::Row::Row() : - m_offset(0), - m_cfa_reg_num(LLDB_INVALID_REGNUM), - m_cfa_offset(0), - m_register_locations() + m_offset (0), + m_cfa_type (CFAIsRegisterPlusOffset), + m_cfa_reg_num (LLDB_INVALID_REGNUM), + m_cfa_offset (0), + m_register_locations () { } @@ -208,6 +210,16 @@ UnwindPlan::Row::GetRegisterInfo (uint32_t reg_num, UnwindPlan::Row::RegisterLoc return false; } +void +UnwindPlan::Row::RemoveRegisterInfo (uint32_t reg_num) +{ + collection::const_iterator pos = m_register_locations.find(reg_num); + if (pos != m_register_locations.end()) + { + m_register_locations.erase(pos); + } +} + void UnwindPlan::Row::SetRegisterInfo (uint32_t reg_num, const UnwindPlan::Row::RegisterLocation register_location) { @@ -301,6 +313,23 @@ UnwindPlan::Row::operator == (const UnwindPlan::Row& rhs) const { if (m_offset != rhs.m_offset || m_cfa_reg_num != rhs.m_cfa_reg_num || m_cfa_offset != rhs.m_cfa_offset) return false; + + if (m_cfa_type != rhs.m_cfa_type) + return false; + + if (m_cfa_type == CFAIsRegisterPlusOffset) + { + if (m_cfa_reg_num != rhs.m_cfa_reg_num) + return false; + if (m_cfa_offset != rhs.m_cfa_offset) + return false; + } + if (m_cfa_type == CFAIsRegisterDereferenced) + { + if (m_cfa_reg_num != rhs.m_cfa_reg_num) + return false; + } + return m_register_locations == rhs.m_register_locations; } @@ -449,6 +478,44 @@ UnwindPlan::Dump (Stream& s, Thread *thread, lldb::addr_t base_addr) const { s.Printf ("This UnwindPlan originally sourced from %s\n", m_source_name.GetCString()); } + if (m_lsda_address.IsValid() && m_personality_func_addr.IsValid()) + { + TargetSP target_sp(thread->CalculateTarget()); + addr_t lsda_load_addr = m_lsda_address.GetLoadAddress (target_sp.get()); + addr_t personality_func_load_addr = m_personality_func_addr.GetLoadAddress (target_sp.get()); + + if (lsda_load_addr != LLDB_INVALID_ADDRESS && personality_func_load_addr != LLDB_INVALID_ADDRESS) + { + s.Printf("LSDA address 0x%" PRIx64 ", personality routine is at address 0x%" PRIx64 "\n", + lsda_load_addr, personality_func_load_addr); + } + } + s.Printf ("This UnwindPlan is sourced from the compiler: "); + switch (m_plan_is_sourced_from_compiler) + { + case eLazyBoolYes: + s.Printf ("yes.\n"); + break; + case eLazyBoolNo: + s.Printf ("no.\n"); + break; + case eLazyBoolCalculate: + s.Printf ("not specified.\n"); + break; + } + s.Printf ("This UnwindPlan is valid at all instruction locations: "); + switch (m_plan_is_valid_at_all_instruction_locations) + { + case eLazyBoolYes: + s.Printf ("yes.\n"); + break; + case eLazyBoolNo: + s.Printf ("no.\n"); + break; + case eLazyBoolCalculate: + s.Printf ("not specified.\n"); + break; + } if (m_plan_valid_address_range.GetBaseAddress().IsValid() && m_plan_valid_address_range.GetByteSize() > 0) { s.PutCString ("Address range of this UnwindPlan: "); diff --git a/source/Symbol/UnwindTable.cpp b/source/Symbol/UnwindTable.cpp index df9f5b932565..90b33a69a789 100644 --- a/source/Symbol/UnwindTable.cpp +++ b/source/Symbol/UnwindTable.cpp @@ -17,6 +17,7 @@ #include "lldb/Symbol/FuncUnwinders.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" +#include "lldb/Symbol/CompactUnwindInfo.h" // There is one UnwindTable object per ObjectFile. // It contains a list of Unwind objects -- one per function, populated lazily -- for the ObjectFile. @@ -30,7 +31,8 @@ UnwindTable::UnwindTable (ObjectFile& objfile) : m_unwinds (), m_initialized (false), m_mutex (), - m_eh_frame (nullptr) + m_eh_frame (nullptr), + m_compact_unwind (nullptr) { } @@ -56,6 +58,11 @@ UnwindTable::Initialize () { m_eh_frame = new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindGCC, true); } + sect = sl->FindSectionByType (eSectionTypeCompactUnwind, true); + if (sect.get()) + { + m_compact_unwind = new CompactUnwindInfo(m_object_file, sect); + } } m_initialized = true; @@ -154,6 +161,13 @@ UnwindTable::GetEHFrameInfo () return m_eh_frame; } +CompactUnwindInfo * +UnwindTable::GetCompactUnwindInfo () +{ + Initialize(); + return m_compact_unwind; +} + bool UnwindTable::GetArchitecture (lldb_private::ArchSpec &arch) { diff --git a/source/Symbol/Variable.cpp b/source/Symbol/Variable.cpp index e6a9b027fc13..b1a60f6b4a24 100644 --- a/source/Symbol/Variable.cpp +++ b/source/Symbol/Variable.cpp @@ -174,13 +174,15 @@ Variable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module) sc.block = nullptr; sc.line_entry.Clear(); bool show_inlined_frames = false; + const bool show_function_arguments = true; dumped_declaration_info = sc.DumpStopContext (s, nullptr, Address(), show_fullpaths, show_module, - show_inlined_frames); + show_inlined_frames, + show_function_arguments); if (sc.function) s->PutChar(':'); diff --git a/source/Target/CPPLanguageRuntime.cpp b/source/Target/CPPLanguageRuntime.cpp index f5b7f7fc41a6..f048c6706a9b 100644 --- a/source/Target/CPPLanguageRuntime.cpp +++ b/source/Target/CPPLanguageRuntime.cpp @@ -11,6 +11,8 @@ #include +#include "llvm/ADT/StringRef.h" + #include "lldb/Core/PluginManager.h" #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Target/ExecutionContext.h" @@ -190,30 +192,17 @@ CPPLanguageRuntime::IsCPPMangledName (const char *name) } bool -CPPLanguageRuntime::StripNamespacesFromVariableName (const char *name, const char *&base_name_start, const char *&base_name_end) +CPPLanguageRuntime::ExtractContextAndIdentifier (const char *name, llvm::StringRef &context, llvm::StringRef &identifier) { - if (base_name_end == NULL) - base_name_end = name + strlen (name); - - const char *last_colon = strrchr (name, ':'); - - if (last_colon == NULL) - { - base_name_start = name; - return true; - } - - // Can't have a C++ name that begins with a single ':', nor contains an internal single ':' - if (last_colon == name) - return false; - else if (last_colon[-1] != ':') - return false; - else + static RegularExpression g_basename_regex("^(([A-Za-z_][A-Za-z_0-9]*::)*)([A-Za-z_][A-Za-z_0-9]*)$"); + RegularExpression::Match match(4); + if (g_basename_regex.Execute (name, &match)) { - // FIXME: should check if there is - base_name_start = last_colon + 1; + match.GetMatchAtIndex(name, 1, context); + match.GetMatchAtIndex(name, 3, identifier); return true; } + return false; } uint32_t @@ -282,6 +271,7 @@ ReverseFindMatchingChars (const llvm::StringRef &s, return false; } + void CPPLanguageRuntime::MethodName::Parse() { @@ -306,6 +296,7 @@ CPPLanguageRuntime::MethodName::Parse() if (arg_start > 0) { size_t basename_end = arg_start; + size_t context_start = 0; size_t context_end = llvm::StringRef::npos; if (basename_end > 0 && full[basename_end-1] == '>') { @@ -314,16 +305,35 @@ CPPLanguageRuntime::MethodName::Parse() size_t template_start, template_end; llvm::StringRef lt_gt("<>", 2); if (ReverseFindMatchingChars (full, lt_gt, template_start, template_end, basename_end)) + { context_end = full.rfind(':', template_start); + if (context_end == llvm::StringRef::npos) + { + // Check for templated functions that include return type like: + // 'void foo()' + context_end = full.rfind(' ', template_start); + if (context_end != llvm::StringRef::npos) + { + context_start = context_end; + } + } + } + else + { + context_end = full.rfind(':', basename_end); + } } - if (context_end == llvm::StringRef::npos) + else if (context_end == llvm::StringRef::npos) + { context_end = full.rfind(':', basename_end); + } if (context_end == llvm::StringRef::npos) m_basename = full.substr(0, basename_end); else { - m_context = full.substr(0, context_end - 1); + if (context_start < context_end) + m_context = full.substr(context_start, context_end - 1); const size_t basename_begin = context_end + 1; m_basename = full.substr(basename_begin, basename_end - basename_begin); } @@ -343,6 +353,30 @@ CPPLanguageRuntime::MethodName::Parse() // printf (" arguments = '%s'\n", m_arguments.str().c_str()); // if (!m_qualifiers.empty()) // printf ("qualifiers = '%s'\n", m_qualifiers.str().c_str()); + + // Make sure we have a valid C++ basename with optional template args + static RegularExpression g_identifier_regex("^~?([A-Za-z_][A-Za-z_0-9]*)(<.*>)?$"); + std::string basename_str(m_basename.str()); + bool basename_is_valid = g_identifier_regex.Execute (basename_str.c_str(), NULL); + if (!basename_is_valid) + { + // Check for C++ operators + if (m_basename.startswith("operator")) + { + static RegularExpression g_operator_regex("^(operator)( ?)([A-Za-z_][A-Za-z_0-9]*|\\(\\)|\\[\\]|[\\^<>=!\\/*+-]+)(<.*>)?(\\[\\])?$"); + basename_is_valid = g_operator_regex.Execute(basename_str.c_str(), NULL); + } + } + if (!basename_is_valid) + { + // The C++ basename doesn't match our regular expressions so this can't + // be a valid C++ method, clear everything out and indicate an error + m_context = llvm::StringRef(); + m_basename = llvm::StringRef(); + m_arguments = llvm::StringRef(); + m_qualifiers = llvm::StringRef(); + m_parse_error = true; + } } else { diff --git a/source/Target/FileAction.cpp b/source/Target/FileAction.cpp index 18b039998bc7..8611ff5f2d2c 100644 --- a/source/Target/FileAction.cpp +++ b/source/Target/FileAction.cpp @@ -13,6 +13,7 @@ #include "lldb/Host/Windows/win32.h" // For O_NOCTTY #endif +#include "lldb/Core/Stream.h" #include "lldb/Target/FileAction.h" using namespace lldb_private; @@ -21,11 +22,11 @@ using namespace lldb_private; // FileAction member functions //---------------------------------------------------------------------------- -FileAction::FileAction() - : m_action(eFileActionNone) - , m_fd(-1) - , m_arg(-1) - , m_path() +FileAction::FileAction() : + m_action(eFileActionNone), + m_fd(-1), + m_arg(-1), + m_path() { } @@ -93,3 +94,24 @@ FileAction::Duplicate(int fd, int dup_fd) } return m_fd >= 0; } + +void +FileAction::Dump(Stream &stream) const +{ + stream.PutCString("file action: "); + switch (m_action) + { + case eFileActionClose: + stream.Printf("close fd %d", m_fd); + break; + case eFileActionDuplicate: + stream.Printf("duplicate fd %d to %d", m_fd, m_arg); + break; + case eFileActionNone: + stream.PutCString("no action"); + break; + case eFileActionOpen: + stream.Printf("open fd %d with '%s', OFLAGS = 0x%x", m_fd, m_path.c_str(), m_arg); + break; + } +} diff --git a/source/Target/InstrumentationRuntime.cpp b/source/Target/InstrumentationRuntime.cpp new file mode 100644 index 000000000000..b3b2393b0234 --- /dev/null +++ b/source/Target/InstrumentationRuntime.cpp @@ -0,0 +1,48 @@ +//===-- InstrumentationRuntime.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/lldb-private.h" +#include "lldb/Target/Process.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Target/InstrumentationRuntime.h" + +using namespace lldb; +using namespace lldb_private; + +void +InstrumentationRuntime::ModulesDidLoad(lldb_private::ModuleList &module_list, lldb_private::Process *process, InstrumentationRuntimeCollection &runtimes) +{ + InstrumentationRuntimeCreateInstance create_callback = NULL; + InstrumentationRuntimeGetType get_type_callback; + for (uint32_t idx = 0; ; ++idx) + { + create_callback = PluginManager::GetInstrumentationRuntimeCreateCallbackAtIndex(idx); + if (create_callback == NULL) + break; + get_type_callback = PluginManager::GetInstrumentationRuntimeGetTypeCallbackAtIndex(idx); + InstrumentationRuntimeType type = get_type_callback(); + + InstrumentationRuntimeCollection::iterator pos; + pos = runtimes.find (type); + if (pos == runtimes.end()) { + runtimes[type] = create_callback(process->shared_from_this()); + } + } +} + +void +InstrumentationRuntime::ModulesDidLoad(lldb_private::ModuleList &module_list) +{ +} + +bool +InstrumentationRuntime::IsActive() +{ + return false; +} diff --git a/source/Target/InstrumentationRuntimeStopInfo.cpp b/source/Target/InstrumentationRuntimeStopInfo.cpp new file mode 100644 index 000000000000..cdbf93b5f720 --- /dev/null +++ b/source/Target/InstrumentationRuntimeStopInfo.cpp @@ -0,0 +1,36 @@ +//===-- InstrumentationRuntimeStopInfo.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Target/InstrumentationRuntimeStopInfo.h" + +#include "lldb/lldb-private.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/InstrumentationRuntime.h" + +using namespace lldb; +using namespace lldb_private; + +InstrumentationRuntimeStopInfo::InstrumentationRuntimeStopInfo(Thread &thread, std::string description, StructuredData::ObjectSP additional_data) : + StopInfo(thread, 0) +{ + m_extended_info = additional_data; + m_description = description; +} + +const char * +InstrumentationRuntimeStopInfo::GetDescription () +{ + return m_description.c_str(); +} + +StopInfoSP +InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData (Thread &thread, std::string description, StructuredData::ObjectSP additionalData) +{ + return StopInfoSP(new InstrumentationRuntimeStopInfo(thread, description, additionalData)); +} diff --git a/source/Target/LanguageRuntime.cpp b/source/Target/LanguageRuntime.cpp index 9d48d8b2de7f..358bffee3a4d 100644 --- a/source/Target/LanguageRuntime.cpp +++ b/source/Target/LanguageRuntime.cpp @@ -10,6 +10,7 @@ #include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/Target.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/SearchFilter.h" using namespace lldb; using namespace lldb_private; @@ -19,17 +20,22 @@ class ExceptionSearchFilter : public SearchFilter { public: ExceptionSearchFilter (const lldb::TargetSP &target_sp, - lldb::LanguageType language) : + lldb::LanguageType language, + bool update_module_list = true) : SearchFilter (target_sp), m_language (language), m_language_runtime (NULL), m_filter_sp () { - UpdateModuleListIfNeeded (); + if (update_module_list) + UpdateModuleListIfNeeded (); } - - virtual bool - ModulePasses (const lldb::ModuleSP &module_sp) + + virtual + ~ExceptionSearchFilter() {}; + + bool + ModulePasses (const lldb::ModuleSP &module_sp) override { UpdateModuleListIfNeeded (); if (m_filter_sp) @@ -37,8 +43,8 @@ public: return false; } - virtual bool - ModulePasses (const FileSpec &spec) + bool + ModulePasses (const FileSpec &spec) override { UpdateModuleListIfNeeded (); if (m_filter_sp) @@ -47,16 +53,16 @@ public: } - virtual void - Search (Searcher &searcher) + void + Search (Searcher &searcher) override { UpdateModuleListIfNeeded (); if (m_filter_sp) m_filter_sp->Search (searcher); } - virtual void - GetDescription (Stream *s) + void + GetDescription (Stream *s) override { UpdateModuleListIfNeeded (); if (m_filter_sp) @@ -68,6 +74,12 @@ protected: LanguageRuntime *m_language_runtime; SearchFilterSP m_filter_sp; + SearchFilterSP + DoCopyForBreakpoint(Breakpoint &breakpoint) override + { + return SearchFilterSP(new ExceptionSearchFilter(TargetSP(), m_language, false)); + } + void UpdateModuleListIfNeeded () { @@ -124,11 +136,11 @@ public: { } - virtual Searcher::CallbackReturn + Searcher::CallbackReturn SearchCallback (SearchFilter &filter, SymbolContext &context, Address *addr, - bool containing) + bool containing) override { if (SetActualResolver()) @@ -137,8 +149,8 @@ public: return eCallbackReturnStop; } - virtual Searcher::Depth - GetDepth () + Searcher::Depth + GetDepth () override { if (SetActualResolver()) return m_actual_resolver_sp->GetDepth(); @@ -146,8 +158,8 @@ public: return eDepthTarget; } - virtual void - GetDescription (Stream *s) + void + GetDescription (Stream *s) override { s->Printf ("Exception breakpoint (catch: %s throw: %s)", m_catch_bp ? "on" : "off", @@ -163,8 +175,8 @@ public: s->Printf (" the correct runtime exception handler will be determined when you run"); } - virtual void - Dump (Stream *s) const + void + Dump (Stream *s) const override { } @@ -174,6 +186,12 @@ public: return V->getResolverID() == BreakpointResolver::ExceptionResolver; } protected: + BreakpointResolverSP + CopyForBreakpoint (Breakpoint &breakpoint) override + { + return BreakpointResolverSP(new ExceptionBreakpointResolver(m_language, m_catch_bp, m_throw_bp)); + } + bool SetActualResolver() { diff --git a/source/Target/Memory.cpp b/source/Target/Memory.cpp index b212fcd23a45..934bc967b68b 100644 --- a/source/Target/Memory.cpp +++ b/source/Target/Memory.cpp @@ -26,7 +26,7 @@ using namespace lldb_private; //---------------------------------------------------------------------- MemoryCache::MemoryCache(Process &process) : m_process (process), - m_cache_line_byte_size (512), + m_cache_line_byte_size (process.GetMemoryCacheLineSize()), m_mutex (Mutex::eMutexTypeRecursive), m_cache (), m_invalid_ranges () @@ -47,6 +47,7 @@ MemoryCache::Clear(bool clear_invalid_ranges) m_cache.clear(); if (clear_invalid_ranges) m_invalid_ranges.Clear(); + m_cache_line_byte_size = m_process.GetMemoryCacheLineSize(); } void @@ -250,7 +251,8 @@ AllocatedBlock::ReserveBlock (uint32_t size) { m_offset_to_chunk_size[0] = needed_chunks; if (log) - log->Printf ("[1] AllocatedBlock::ReserveBlock(%p) (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks", this, size, size, 0, needed_chunks, m_chunk_size); + log->Printf("[1] AllocatedBlock::ReserveBlock(%p) (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks", (void *)this, + size, size, 0, needed_chunks, m_chunk_size); addr = m_addr; } else @@ -268,7 +270,9 @@ AllocatedBlock::ReserveBlock (uint32_t size) { m_offset_to_chunk_size[last_offset] = needed_chunks; if (log) - log->Printf ("[2] AllocatedBlock::ReserveBlock(%p) (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks - num_chunks %lu", this, size, size, last_offset, needed_chunks, m_chunk_size, m_offset_to_chunk_size.size()); + log->Printf("[2] AllocatedBlock::ReserveBlock(%p) (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks - " + "num_chunks %lu", + (void *)this, size, size, last_offset, needed_chunks, m_chunk_size, m_offset_to_chunk_size.size()); addr = m_addr + last_offset; break; } @@ -284,7 +288,9 @@ AllocatedBlock::ReserveBlock (uint32_t size) { m_offset_to_chunk_size[last_offset] = needed_chunks; if (log) - log->Printf ("[3] AllocatedBlock::ReserveBlock(%p) (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks - num_chunks %lu", this, size, size, last_offset, needed_chunks, m_chunk_size, m_offset_to_chunk_size.size()); + log->Printf("[3] AllocatedBlock::ReserveBlock(%p) (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks - " + "num_chunks %lu", + (void *)this, size, size, last_offset, needed_chunks, m_chunk_size, m_offset_to_chunk_size.size()); addr = m_addr + last_offset; break; } @@ -345,7 +351,7 @@ AllocatedBlock::ReserveBlock (uint32_t size) } if (log) - log->Printf ("AllocatedBlock::ReserveBlock(%p) (size = %u (0x%x)) => 0x%16.16" PRIx64, this, size, size, (uint64_t)addr); + log->Printf("AllocatedBlock::ReserveBlock(%p) (size = %u (0x%x)) => 0x%16.16" PRIx64, (void *)this, size, size, (uint64_t)addr); return addr; } @@ -362,7 +368,8 @@ AllocatedBlock::FreeBlock (addr_t addr) } Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); if (log) - log->Printf ("AllocatedBlock::FreeBlock(%p) (addr = 0x%16.16" PRIx64 ") => %i, num_chunks: %lu", this, (uint64_t)addr, success, m_offset_to_chunk_size.size()); + log->Printf("AllocatedBlock::FreeBlock(%p) (addr = 0x%16.16" PRIx64 ") => %i, num_chunks: %lu", (void *)this, (uint64_t)addr, + success, m_offset_to_chunk_size.size()); return success; } diff --git a/source/Target/MemoryHistory.cpp b/source/Target/MemoryHistory.cpp new file mode 100644 index 000000000000..b97096b06d76 --- /dev/null +++ b/source/Target/MemoryHistory.cpp @@ -0,0 +1,30 @@ +//===-- MemoryHistory.cpp -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Target/MemoryHistory.h" + +#include "lldb/Core/PluginManager.h" + +using namespace lldb; +using namespace lldb_private; + +lldb::MemoryHistorySP +MemoryHistory::FindPlugin (const ProcessSP process) +{ + MemoryHistoryCreateInstance create_callback = NULL; + + for (uint32_t idx = 0; (create_callback = PluginManager::GetMemoryHistoryCreateCallbackAtIndex(idx)) != NULL; ++idx) + { + MemoryHistorySP memory_history_sp (create_callback (process)); + if (memory_history_sp.get()) + return memory_history_sp; + } + + return MemoryHistorySP(); +} diff --git a/source/Target/ObjCLanguageRuntime.cpp b/source/Target/ObjCLanguageRuntime.cpp index 1f2abd876c84..b182407bf68e 100644 --- a/source/Target/ObjCLanguageRuntime.cpp +++ b/source/Target/ObjCLanguageRuntime.cpp @@ -603,20 +603,20 @@ ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa) ClangASTType -ObjCLanguageRuntime::EncodingToType::RealizeType (const char* name, bool allow_unknownanytype) +ObjCLanguageRuntime::EncodingToType::RealizeType (const char* name, bool for_expression) { if (m_scratch_ast_ctx_ap) - return RealizeType(*m_scratch_ast_ctx_ap, name, allow_unknownanytype); + return RealizeType(*m_scratch_ast_ctx_ap, name, for_expression); return ClangASTType(); } ClangASTType -ObjCLanguageRuntime::EncodingToType::RealizeType (ClangASTContext& ast_ctx, const char* name, bool allow_unknownanytype) +ObjCLanguageRuntime::EncodingToType::RealizeType (ClangASTContext& ast_ctx, const char* name, bool for_expression) { clang::ASTContext *clang_ast = ast_ctx.getASTContext(); if (!clang_ast) return ClangASTType(); - return RealizeType(*clang_ast, name, allow_unknownanytype); + return RealizeType(*clang_ast, name, for_expression); } ObjCLanguageRuntime::EncodingToType::~EncodingToType() {} diff --git a/source/Target/Platform.cpp b/source/Target/Platform.cpp index fe73be2d05b9..4ebd18b8bfd0 100644 --- a/source/Target/Platform.cpp +++ b/source/Target/Platform.cpp @@ -32,26 +32,12 @@ using namespace lldb_private; // Use a singleton function for g_local_platform_sp to avoid init // constructors since LLDB is often part of a shared library static PlatformSP& -GetDefaultPlatformSP () +GetHostPlatformSP () { - static PlatformSP g_default_platform_sp; - return g_default_platform_sp; + static PlatformSP g_platform_sp; + return g_platform_sp; } -static Mutex & -GetConnectedPlatformListMutex () -{ - static Mutex g_remote_connected_platforms_mutex (Mutex::eMutexTypeRecursive); - return g_remote_connected_platforms_mutex; -} -static std::vector & -GetConnectedPlatformList () -{ - static std::vector g_remote_connected_platforms; - return g_remote_connected_platforms; -} - - const char * Platform::GetHostPlatformName () { @@ -69,17 +55,37 @@ Platform::GetHostPlatformName () /// or attaching to processes unless another platform is specified. //------------------------------------------------------------------ PlatformSP -Platform::GetDefaultPlatform () +Platform::GetHostPlatform () { - return GetDefaultPlatformSP (); + return GetHostPlatformSP (); +} + +static std::vector & +GetPlatformList() +{ + static std::vector g_platform_list; + return g_platform_list; +} + +static Mutex & +GetPlatformListMutex () +{ + static Mutex g_mutex(Mutex::eMutexTypeRecursive); + return g_mutex; } void -Platform::SetDefaultPlatform (const lldb::PlatformSP &platform_sp) +Platform::SetHostPlatform (const lldb::PlatformSP &platform_sp) { // The native platform should use its static void Platform::Initialize() // function to register itself as the native platform. - GetDefaultPlatformSP () = platform_sp; + GetHostPlatformSP () = platform_sp; + + if (platform_sp) + { + Mutex::Locker locker(GetPlatformListMutex ()); + GetPlatformList().push_back(platform_sp); + } } Error @@ -98,36 +104,36 @@ Platform::LocateExecutableScriptingResources (Target *target, Module &module, St return FileSpecList(); } -Platform* -Platform::FindPlugin (Process *process, const ConstString &plugin_name) -{ - PlatformCreateInstance create_callback = NULL; - if (plugin_name) - { - create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (plugin_name); - if (create_callback) - { - ArchSpec arch; - if (process) - { - arch = process->GetTarget().GetArchitecture(); - } - std::unique_ptr instance_ap(create_callback(process, &arch)); - if (instance_ap.get()) - return instance_ap.release(); - } - } - else - { - for (uint32_t idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != NULL; ++idx) - { - std::unique_ptr instance_ap(create_callback(process, nullptr)); - if (instance_ap.get()) - return instance_ap.release(); - } - } - return NULL; -} +//PlatformSP +//Platform::FindPlugin (Process *process, const ConstString &plugin_name) +//{ +// PlatformCreateInstance create_callback = NULL; +// if (plugin_name) +// { +// create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (plugin_name); +// if (create_callback) +// { +// ArchSpec arch; +// if (process) +// { +// arch = process->GetTarget().GetArchitecture(); +// } +// PlatformSP platform_sp(create_callback(process, &arch)); +// if (platform_sp) +// return platform_sp; +// } +// } +// else +// { +// for (uint32_t idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != NULL; ++idx) +// { +// PlatformSP platform_sp(create_callback(process, nullptr)); +// if (platform_sp) +// return platform_sp; +// } +// } +// return PlatformSP(); +//} Error Platform::GetSharedModule (const ModuleSpec &module_spec, @@ -153,21 +159,50 @@ Platform::GetSharedModule (const ModuleSpec &module_spec, } PlatformSP -Platform::Create (const char *platform_name, Error &error) +Platform::Find (const ConstString &name) +{ + if (name) + { + static ConstString g_host_platform_name ("host"); + if (name == g_host_platform_name) + return GetHostPlatform(); + + Mutex::Locker locker(GetPlatformListMutex ()); + for (const auto &platform_sp : GetPlatformList()) + { + if (platform_sp->GetName() == name) + return platform_sp; + } + } + return PlatformSP(); +} + +PlatformSP +Platform::Create (const ConstString &name, Error &error) { PlatformCreateInstance create_callback = NULL; lldb::PlatformSP platform_sp; - if (platform_name && platform_name[0]) + if (name) { - ConstString const_platform_name (platform_name); - create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (const_platform_name); + static ConstString g_host_platform_name ("host"); + if (name == g_host_platform_name) + return GetHostPlatform(); + + create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (name); if (create_callback) - platform_sp.reset(create_callback(true, NULL)); + platform_sp = create_callback(true, NULL); else - error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name); + error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", name.GetCString()); } else error.SetErrorString ("invalid platform name"); + + if (platform_sp) + { + Mutex::Locker locker(GetPlatformListMutex ()); + GetPlatformList().push_back(platform_sp); + } + return platform_sp; } @@ -178,28 +213,52 @@ Platform::Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &erro lldb::PlatformSP platform_sp; if (arch.IsValid()) { - uint32_t idx; + // Scope for locker + { + // First try exact arch matches across all platforms already created + Mutex::Locker locker(GetPlatformListMutex ()); + for (const auto &platform_sp : GetPlatformList()) + { + if (platform_sp->IsCompatibleArchitecture(arch, true, platform_arch_ptr)) + return platform_sp; + } + + // Next try compatible arch matches across all platforms already created + for (const auto &platform_sp : GetPlatformList()) + { + if (platform_sp->IsCompatibleArchitecture(arch, false, platform_arch_ptr)) + return platform_sp; + } + } + PlatformCreateInstance create_callback; // First try exact arch matches across all platform plug-ins - bool exact = true; + uint32_t idx; for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx) { if (create_callback) { - platform_sp.reset(create_callback(false, &arch)); - if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr)) + platform_sp = create_callback(false, &arch); + if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, true, platform_arch_ptr)) + { + Mutex::Locker locker(GetPlatformListMutex ()); + GetPlatformList().push_back(platform_sp); return platform_sp; + } } } // Next try compatible arch matches across all platform plug-ins - exact = false; for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx) { if (create_callback) { - platform_sp.reset(create_callback(false, &arch)); - if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr)) + platform_sp = create_callback(false, &arch); + if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, false, platform_arch_ptr)) + { + Mutex::Locker locker(GetPlatformListMutex ()); + GetPlatformList().push_back(platform_sp); return platform_sp; + } } } } @@ -211,25 +270,6 @@ Platform::Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &erro return platform_sp; } -uint32_t -Platform::GetNumConnectedRemotePlatforms () -{ - Mutex::Locker locker (GetConnectedPlatformListMutex ()); - return GetConnectedPlatformList().size(); -} - -PlatformSP -Platform::GetConnectedRemotePlatformAtIndex (uint32_t idx) -{ - PlatformSP platform_sp; - { - Mutex::Locker locker (GetConnectedPlatformListMutex ()); - if (idx < GetConnectedPlatformList().size()) - platform_sp = GetConnectedPlatformList ()[idx]; - } - return platform_sp; -} - //------------------------------------------------------------------ /// Default Constructor //------------------------------------------------------------------ @@ -422,6 +462,20 @@ Platform::GetOSKernelDescription (std::string &s) return GetRemoteOSKernelDescription (s); } +void +Platform::AddClangModuleCompilationOptions (std::vector &options) +{ + std::vector default_compilation_options = + { + "-x", "c++", "-Xclang", "-nostdsysteminc", "-Xclang", "-nostdsysteminc" + }; + + options.insert(options.end(), + default_compilation_options.begin(), + default_compilation_options.end()); +} + + ConstString Platform::GetWorkingDirectory () { @@ -537,11 +591,11 @@ RecurseCopy_Callback (void *baton, case FileSpec::eFileTypeInvalid: case FileSpec::eFileTypeOther: case FileSpec::eFileTypeUnknown: - default: rc_baton->error.SetErrorStringWithFormat("invalid file detected during copy: %s", src.GetPath().c_str()); return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out break; } + llvm_unreachable("Unhandled FileSpec::FileType!"); } Error @@ -842,15 +896,13 @@ Platform::SetOSVersion (uint32_t major, Error -Platform::ResolveExecutable (const FileSpec &exe_file, - const ArchSpec &exe_arch, +Platform::ResolveExecutable (const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, const FileSpecList *module_search_paths_ptr) { Error error; - if (exe_file.Exists()) + if (module_spec.GetFileSpec().Exists()) { - ModuleSpec module_spec (exe_file, exe_arch); if (module_spec.GetArchitecture().IsValid()) { error = ModuleList::GetSharedModule (module_spec, @@ -864,9 +916,10 @@ Platform::ResolveExecutable (const FileSpec &exe_file, // No valid architecture was specified, ask the platform for // the architectures that we should be using (in the correct order) // and see if we can find a match that way - for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx) + ModuleSpec arch_module_spec(module_spec); + for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, arch_module_spec.GetArchitecture()); ++idx) { - error = ModuleList::GetSharedModule (module_spec, + error = ModuleList::GetSharedModule (arch_module_spec, exe_module_sp, module_search_paths_ptr, NULL, @@ -880,7 +933,7 @@ Platform::ResolveExecutable (const FileSpec &exe_file, else { error.SetErrorStringWithFormat ("'%s' does not exist", - exe_file.GetPath().c_str()); + module_spec.GetFileSpec().GetPath().c_str()); } return error; } @@ -1005,7 +1058,11 @@ Error Platform::LaunchProcess (ProcessLaunchInfo &launch_info) { Error error; - // Take care of the host case so that each subclass can just + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); + if (log) + log->Printf ("Platform::%s()", __FUNCTION__); + + // Take care of the host case so that each subclass can just // call this function to get the host functionality. if (IsHost()) { @@ -1018,6 +1075,16 @@ Platform::LaunchProcess (ProcessLaunchInfo &launch_info) const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug); const bool first_arg_is_full_shell_command = false; uint32_t num_resumes = GetResumeCountForLaunchInfo (launch_info); + if (log) + { + const FileSpec &shell = launch_info.GetShell(); + const char *shell_str = (shell) ? shell.GetPath().c_str() : ""; + log->Printf ("Platform::%s GetResumeCountForLaunchInfo() returned %" PRIu32 ", shell is '%s'", + __FUNCTION__, + num_resumes, + shell_str); + } + if (!launch_info.ConvertArgumentsForLaunchingInShell (error, is_localhost, will_debug, @@ -1026,6 +1093,9 @@ Platform::LaunchProcess (ProcessLaunchInfo &launch_info) return error; } + if (log) + log->Printf ("Platform::%s final launch_info resume count: %" PRIu32, __FUNCTION__, launch_info.GetResumeCount ()); + error = Host::LaunchProcess (launch_info); } else @@ -1037,9 +1107,12 @@ lldb::ProcessSP Platform::DebugProcess (ProcessLaunchInfo &launch_info, Debugger &debugger, Target *target, // Can be NULL, if NULL create a new target, else use existing one - Listener &listener, Error &error) { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); + if (log) + log->Printf ("Platform::%s entered (target %p)", __FUNCTION__, static_cast(target)); + ProcessSP process_sp; // Make sure we stop at the entry point launch_info.GetFlags ().Set (eLaunchFlagDebug); @@ -1051,12 +1124,16 @@ Platform::DebugProcess (ProcessLaunchInfo &launch_info, error = LaunchProcess (launch_info); if (error.Success()) { + if (log) + log->Printf ("Platform::%s LaunchProcess() call succeeded (pid=%" PRIu64 ")", __FUNCTION__, launch_info.GetProcessID ()); if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { ProcessAttachInfo attach_info (launch_info); - process_sp = Attach (attach_info, debugger, target, listener, error); + process_sp = Attach (attach_info, debugger, target, error); if (process_sp) { + if (log) + log->Printf ("Platform::%s Attach() succeeded, Process plugin: %s", __FUNCTION__, process_sp->GetPluginName ().AsCString ()); launch_info.SetHijackListener(attach_info.GetHijackListener()); // Since we attached to the process, it will think it needs to detach @@ -1075,8 +1152,24 @@ Platform::DebugProcess (ProcessLaunchInfo &launch_info, process_sp->SetSTDIOFileDescriptor(pty_fd); } } + else + { + if (log) + log->Printf ("Platform::%s Attach() failed: %s", __FUNCTION__, error.AsCString ()); + } } + else + { + if (log) + log->Printf ("Platform::%s LaunchProcess() returned launch_info with invalid process id", __FUNCTION__); + } + } + else + { + if (log) + log->Printf ("Platform::%s LaunchProcess() failed: %s", __FUNCTION__, error.AsCString ()); } + return process_sp; } diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp index a1049787d821..106678da2684 100644 --- a/source/Target/Process.cpp +++ b/source/Target/Process.cpp @@ -16,22 +16,25 @@ #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Event.h" -#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" -#include "lldb/Symbol/Symbol.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamFile.h" #include "lldb/Expression/ClangUserExpression.h" -#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" #include "lldb/Host/Pipe.h" #include "lldb/Host/Terminal.h" +#include "lldb/Host/ThreadLauncher.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Symbol/Symbol.h" #include "lldb/Target/ABI.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/JITLoader.h" +#include "lldb/Target/MemoryHistory.h" #include "lldb/Target/OperatingSystem.h" #include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/CPPLanguageRuntime.h" @@ -45,6 +48,7 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanBase.h" +#include "lldb/Target/InstrumentationRuntime.h" #include "Plugins/Process/Utility/InferiorCallPOSIX.h" using namespace lldb; @@ -108,6 +112,7 @@ g_properties[] = { "python-os-plugin-path", OptionValue::eTypeFileSpec, false, true, NULL, NULL, "A path to a python OS plug-in module file that contains a OperatingSystemPlugIn class." }, { "stop-on-sharedlibrary-events" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, stop when a shared library is loaded or unloaded." }, { "detach-keeps-stopped" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, detach will attempt to keep the process stopped." }, + { "memory-cache-line-size" , OptionValue::eTypeUInt64, false, 512, NULL, NULL, "The memory cache line size" }, { NULL , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL } }; @@ -118,14 +123,17 @@ enum { ePropertyUnwindOnErrorInExpressions, ePropertyPythonOSPluginPath, ePropertyStopOnSharedLibraryEvents, - ePropertyDetachKeepsStopped + ePropertyDetachKeepsStopped, + ePropertyMemCacheLineSize }; -ProcessProperties::ProcessProperties (bool is_global) : - Properties () +ProcessProperties::ProcessProperties (lldb_private::Process *process) : + Properties (), + m_process (process) // Can be NULL for global ProcessProperties { - if (is_global) + if (process == NULL) { + // Global process properties, set them up one time m_collection_sp.reset (new ProcessOptionValueProperties(ConstString("process"))); m_collection_sp->Initialize(g_properties); m_collection_sp->AppendProperty(ConstString("thread"), @@ -134,13 +142,24 @@ ProcessProperties::ProcessProperties (bool is_global) : Thread::GetGlobalProperties()->GetValueProperties()); } else + { m_collection_sp.reset (new ProcessOptionValueProperties(Process::GetGlobalProperties().get())); + m_collection_sp->SetValueChangedCallback(ePropertyPythonOSPluginPath, ProcessProperties::OptionValueChangedCallback, this); + } } ProcessProperties::~ProcessProperties() { } +void +ProcessProperties::OptionValueChangedCallback (void *baton, OptionValue *option_value) +{ + ProcessProperties *properties = (ProcessProperties *)baton; + if (properties->m_process) + properties->m_process->LoadOperatingSystemPlugin(true); +} + bool ProcessProperties::GetDisableMemoryCache() const { @@ -148,6 +167,13 @@ ProcessProperties::GetDisableMemoryCache() const return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); } +uint64_t +ProcessProperties::GetMemoryCacheLineSize() const +{ + const uint32_t idx = ePropertyMemCacheLineSize; + return m_collection_sp->GetPropertyAtIndexAsUInt64 (NULL, idx, g_properties[idx].default_uint_value); +} + Args ProcessProperties::GetExtraStartupCommands () const { @@ -467,9 +493,9 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op case 'c': if (option_arg && option_arg[0]) - launch_info.SetShell (option_arg); + launch_info.SetShell (FileSpec(option_arg, false)); else - launch_info.SetShell (LLDB_DEFAULT_SHELL); + launch_info.SetShell (HostInfo::GetDefaultShell()); break; case 'v': @@ -660,7 +686,7 @@ Process::Process(Target &target, Listener &listener) : } Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_signals_sp) : - ProcessProperties (false), + ProcessProperties (this), UserID (LLDB_INVALID_PROCESS_ID), Broadcaster (&(target.GetDebugger()), "lldb.process"), m_target (target), @@ -670,13 +696,13 @@ Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_s m_private_state_control_broadcaster (NULL, "lldb.process.internal_state_control_broadcaster"), m_private_state_listener ("lldb.process.internal_state_listener"), m_private_state_control_wait(), - m_private_state_thread (LLDB_INVALID_HOST_THREAD), m_mod_id (), m_process_unique_id(0), m_thread_index_id (0), m_thread_id_to_index_id_map (), m_exit_status (-1), m_exit_string (), + m_exit_status_mutex(), m_thread_mutex (Mutex::eMutexTypeRecursive), m_thread_list_real (this), m_thread_list (this), @@ -706,6 +732,7 @@ Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_s m_public_run_lock (), m_private_run_lock (), m_currently_handling_event(false), + m_stop_info_override_callback (NULL), m_finalize_called(false), m_clear_thread_plans_on_stop (false), m_force_next_event_delivery(false), @@ -760,6 +787,11 @@ Process::~Process() if (log) log->Printf ("%p Process::~Process()", static_cast(this)); StopPrivateStateThread(); + + // ThreadList::Clear() will try to acquire this process's mutex, so + // explicitly clear the thread list here to ensure that the mutex + // is not destroyed before the thread list. + m_thread_list.Clear(); } const ProcessPropertiesSP & @@ -767,7 +799,7 @@ Process::GetGlobalProperties() { static ProcessPropertiesSP g_settings_sp; if (!g_settings_sp) - g_settings_sp.reset (new ProcessProperties (true)); + g_settings_sp.reset (new ProcessProperties (NULL)); return g_settings_sp; } @@ -826,7 +858,9 @@ Process::Finalize() m_memory_cache.Clear(); m_allocated_memory_cache.Clear(); m_language_runtimes.clear(); + m_instrumentation_runtimes.clear(); m_next_event_action_ap.reset(); + m_stop_info_override_callback = NULL; //#ifdef LLDB_CONFIGURATION_DEBUG // StreamFile s(stdout, false); // EventSP event_sp; @@ -924,7 +958,7 @@ Process::SyncIOHandler (uint64_t timeout_msec) log->Printf ("Process::%s pid %" PRIu64 ": SUCCESS", __FUNCTION__, GetID ()); } - // reset sync one-shot so it will be ready for next time + // reset sync one-shot so it will be ready for next launch m_iohandler_sync.SetValue(false, eBroadcastNever); } @@ -932,7 +966,11 @@ Process::SyncIOHandler (uint64_t timeout_msec) } StateType -Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr, bool wait_always, Listener *hijack_listener) +Process::WaitForProcessToStop (const TimeValue *timeout, + EventSP *event_sp_ptr, + bool wait_always, + Listener *hijack_listener, + Stream *stream) { // We can't just wait for a "stopped" event, because the stopped event may have restarted the target. // We have to actually check each event, and in the case of a stopped event check the restarted flag @@ -966,6 +1004,9 @@ Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp if (event_sp_ptr && event_sp) *event_sp_ptr = event_sp; + bool pop_process_io_handler = hijack_listener != NULL; + Process::HandleProcessStateChangedEvent (event_sp, stream, pop_process_io_handler); + switch (state) { case eStateCrashed: @@ -995,6 +1036,195 @@ Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp return state; } +bool +Process::HandleProcessStateChangedEvent (const EventSP &event_sp, + Stream *stream, + bool &pop_process_io_handler) +{ + const bool handle_pop = pop_process_io_handler == true; + + pop_process_io_handler = false; + ProcessSP process_sp = Process::ProcessEventData::GetProcessFromEvent(event_sp.get()); + + if (!process_sp) + return false; + + StateType event_state = Process::ProcessEventData::GetStateFromEvent (event_sp.get()); + if (event_state == eStateInvalid) + return false; + + switch (event_state) + { + case eStateInvalid: + case eStateUnloaded: + case eStateAttaching: + case eStateLaunching: + case eStateStepping: + case eStateDetached: + { + if (stream) + stream->Printf ("Process %" PRIu64 " %s\n", + process_sp->GetID(), + StateAsCString (event_state)); + + if (event_state == eStateDetached) + pop_process_io_handler = true; + } + break; + + case eStateConnected: + case eStateRunning: + // Don't be chatty when we run... + break; + + case eStateExited: + if (stream) + process_sp->GetStatus(*stream); + pop_process_io_handler = true; + break; + + case eStateStopped: + case eStateCrashed: + case eStateSuspended: + // Make sure the program hasn't been auto-restarted: + if (Process::ProcessEventData::GetRestartedFromEvent (event_sp.get())) + { + if (stream) + { + size_t num_reasons = Process::ProcessEventData::GetNumRestartedReasons(event_sp.get()); + if (num_reasons > 0) + { + // FIXME: Do we want to report this, or would that just be annoyingly chatty? + if (num_reasons == 1) + { + const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), 0); + stream->Printf ("Process %" PRIu64 " stopped and restarted: %s\n", + process_sp->GetID(), + reason ? reason : ""); + } + else + { + stream->Printf ("Process %" PRIu64 " stopped and restarted, reasons:\n", + process_sp->GetID()); + + + for (size_t i = 0; i < num_reasons; i++) + { + const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), i); + stream->Printf("\t%s\n", reason ? reason : ""); + } + } + } + } + } + else + { + // Lock the thread list so it doesn't change on us, this is the scope for the locker: + { + ThreadList &thread_list = process_sp->GetThreadList(); + Mutex::Locker locker (thread_list.GetMutex()); + + ThreadSP curr_thread (thread_list.GetSelectedThread()); + ThreadSP thread; + StopReason curr_thread_stop_reason = eStopReasonInvalid; + if (curr_thread) + curr_thread_stop_reason = curr_thread->GetStopReason(); + if (!curr_thread || + !curr_thread->IsValid() || + curr_thread_stop_reason == eStopReasonInvalid || + curr_thread_stop_reason == eStopReasonNone) + { + // Prefer a thread that has just completed its plan over another thread as current thread. + ThreadSP plan_thread; + ThreadSP other_thread; + const size_t num_threads = thread_list.GetSize(); + size_t i; + for (i = 0; i < num_threads; ++i) + { + thread = thread_list.GetThreadAtIndex(i); + StopReason thread_stop_reason = thread->GetStopReason(); + switch (thread_stop_reason) + { + case eStopReasonInvalid: + case eStopReasonNone: + break; + + case eStopReasonTrace: + case eStopReasonBreakpoint: + case eStopReasonWatchpoint: + case eStopReasonSignal: + case eStopReasonException: + case eStopReasonExec: + case eStopReasonThreadExiting: + case eStopReasonInstrumentation: + if (!other_thread) + other_thread = thread; + break; + case eStopReasonPlanComplete: + if (!plan_thread) + plan_thread = thread; + break; + } + } + if (plan_thread) + thread_list.SetSelectedThreadByID (plan_thread->GetID()); + else if (other_thread) + thread_list.SetSelectedThreadByID (other_thread->GetID()); + else + { + if (curr_thread && curr_thread->IsValid()) + thread = curr_thread; + else + thread = thread_list.GetThreadAtIndex(0); + + if (thread) + thread_list.SetSelectedThreadByID (thread->GetID()); + } + } + } + // Drop the ThreadList mutex by here, since GetThreadStatus below might have to run code, + // e.g. for Data formatters, and if we hold the ThreadList mutex, then the process is going to + // have a hard time restarting the process. + if (stream) + { + Debugger &debugger = process_sp->GetTarget().GetDebugger(); + if (debugger.GetTargetList().GetSelectedTarget().get() == &process_sp->GetTarget()) + { + const bool only_threads_with_stop_reason = true; + const uint32_t start_frame = 0; + const uint32_t num_frames = 1; + const uint32_t num_frames_with_source = 1; + process_sp->GetStatus(*stream); + process_sp->GetThreadStatus (*stream, + only_threads_with_stop_reason, + start_frame, + num_frames, + num_frames_with_source); + } + else + { + uint32_t target_idx = debugger.GetTargetList().GetIndexOfTarget(process_sp->GetTarget().shared_from_this()); + if (target_idx != UINT32_MAX) + stream->Printf ("Target %d: (", target_idx); + else + stream->Printf ("Target : ("); + process_sp->GetTarget().Dump (stream, eDescriptionLevelBrief); + stream->Printf (") stopped.\n"); + } + } + + // Pop the process IO handler + pop_process_io_handler = true; + } + break; + } + + if (handle_pop && pop_process_io_handler) + process_sp->PopProcessIOHandler(); + + return true; +} + StateType Process::WaitForState @@ -1170,6 +1400,8 @@ Process::IsRunning () const int Process::GetExitStatus () { + Mutex::Locker locker (m_exit_status_mutex); + if (m_public_state.GetValue() == eStateExited) return m_exit_status; return -1; @@ -1179,6 +1411,8 @@ Process::GetExitStatus () const char * Process::GetExitDescription () { + Mutex::Locker locker (m_exit_status_mutex); + if (m_public_state.GetValue() == eStateExited && !m_exit_string.empty()) return m_exit_string.c_str(); return NULL; @@ -1203,11 +1437,16 @@ Process::SetExitStatus (int status, const char *cstr) return false; } - m_exit_status = status; - if (cstr) - m_exit_string = cstr; - else - m_exit_string.clear(); + // use a mutex to protect the status and string during updating + { + Mutex::Locker locker (m_exit_status_mutex); + + m_exit_status = status; + if (cstr) + m_exit_string = cstr; + else + m_exit_string.clear(); + } DidExit (); @@ -1392,6 +1631,17 @@ Process::GetState() return m_public_state.GetValue (); } +bool +Process::StateChangedIsExternallyHijacked() +{ + if (IsHijackedForEvent(eBroadcastBitStateChanged)) + { + if (strcmp(m_hijacking_listeners.back()->GetName(), "lldb.Process.ResumeSynchronous.hijack")) + return true; + } + return false; +} + void Process::SetPublicState (StateType new_state, bool restarted) { @@ -1404,7 +1654,7 @@ Process::SetPublicState (StateType new_state, bool restarted) // On the transition from Run to Stopped, we unlock the writer end of the // run lock. The lock gets locked in Resume, which is the public API // to tell the program to run. - if (!IsHijackedForEvent(eBroadcastBitStateChanged)) + if (!StateChangedIsExternallyHijacked()) { if (new_state == eStateDetached) { @@ -1445,6 +1695,36 @@ Process::Resume () return PrivateResume(); } +Error +Process::ResumeSynchronous (Stream *stream) +{ + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("Process::ResumeSynchronous -- locking run lock"); + if (!m_public_run_lock.TrySetRunning()) + { + Error error("Resume request failed - process still running."); + if (log) + log->Printf ("Process::Resume: -- TrySetRunning failed, not resuming."); + return error; + } + + ListenerSP listener_sp (new Listener("lldb.Process.ResumeSynchronous.hijack")); + HijackProcessEvents(listener_sp.get()); + + Error error = PrivateResume(); + + StateType state = WaitForProcessToStop (NULL, NULL, true, listener_sp.get(), stream); + + // Undo the hijacking of process events... + RestoreProcessEvents(); + + if (error.Success() && !StateIsStoppedState(state, false)) + error.SetErrorStringWithFormat("process not in stopped state after synchronous resume: %s", StateAsCString(state)); + + return error; +} + StateType Process::GetPrivateState () { @@ -1617,12 +1897,17 @@ Process::LoadImage (const FileSpec &image_spec, Error &error) { if (error_str_sp->IsCStringContainer(true)) { - StreamString s; - size_t num_chars = error_str_sp->ReadPointedString (s, error); + DataBufferSP buffer_sp(new DataBufferHeap(10240,0)); + size_t num_chars = error_str_sp->ReadPointedString (buffer_sp, error, 10240); if (error.Success() && num_chars > 0) { error.Clear(); - error.SetErrorStringWithFormat("dlopen error: %s", s.GetData()); + error.SetErrorStringWithFormat("dlopen error: %s", buffer_sp->GetBytes()); + } + else + { + error.Clear(); + error.SetErrorStringWithFormat("dlopen failed for unknown reasons."); } } } @@ -2507,10 +2792,10 @@ Process::WriteMemory (addr_t addr, const void *buf, size_t size, Error &error) }); if (bytes_written < size) - bytes_written += WriteMemoryPrivate (addr + bytes_written, - ubuf + bytes_written, - size - bytes_written, - error); + WriteMemoryPrivate (addr + bytes_written, + ubuf + bytes_written, + size - bytes_written, + error); } } else @@ -2722,6 +3007,16 @@ Process::WaitForProcessStopPrivate (const TimeValue *timeout, EventSP &event_sp) return state; } +void +Process::LoadOperatingSystemPlugin(bool flush) +{ + if (flush) + m_thread_list.Clear(); + m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL)); + if (flush) + Flush(); +} + Error Process::Launch (ProcessLaunchInfo &launch_info) { @@ -2732,6 +3027,7 @@ Process::Launch (ProcessLaunchInfo &launch_info) m_system_runtime_ap.reset(); m_os_ap.reset(); m_process_input_reader.reset(); + m_stop_info_override_callback = NULL; Module *exe_module = m_target.GetExecutableModulePointer(); if (exe_module) @@ -2811,15 +3107,20 @@ Process::Launch (ProcessLaunchInfo &launch_info) if (system_runtime) system_runtime->DidLaunch(); - m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL)); - // This delays passing the stopped event to listeners till DidLaunch gets - // a chance to complete... - HandlePrivateEvent (event_sp); + LoadOperatingSystemPlugin(false); + + // Note, the stop event was consumed above, but not handled. This was done + // to give DidLaunch a chance to run. The target is either stopped or crashed. + // Directly set the state. This is done to prevent a stop message with a bunch + // of spurious output on thread status, as well as not pop a ProcessIOHandler. + SetPublicState(state, false); if (PrivateStateThreadIsValid ()) ResumePrivateStateThread (); else StartPrivateStateThread (); + + m_stop_info_override_callback = GetTarget().GetArchitecture().GetStopInfoOverrideCallback(); } else if (state == eStateExited) { @@ -2979,6 +3280,15 @@ Process::AttachCompletionHandler::GetExitString () return m_exit_string.c_str(); } +Listener & +ProcessAttachInfo::GetListenerForProcess (Debugger &debugger) +{ + if (m_listener_sp) + return *m_listener_sp; + else + return debugger.GetListener(); +} + Error Process::Attach (ProcessAttachInfo &attach_info) { @@ -2988,6 +3298,7 @@ Process::Attach (ProcessAttachInfo &attach_info) m_jit_loaders_ap.reset(); m_system_runtime_ap.reset(); m_os_ap.reset(); + m_stop_info_override_callback = NULL; lldb::pid_t attach_pid = attach_info.GetProcessID(); Error error; @@ -3115,14 +3426,13 @@ Process::Attach (ProcessAttachInfo &attach_info) else { if (GetID() != LLDB_INVALID_PROCESS_ID) - { SetID (LLDB_INVALID_PROCESS_ID); - const char *error_string = error.AsCString(); - if (error_string == NULL) - error_string = "attach failed"; - SetExitStatus(-1, error_string); - } + const char *error_string = error.AsCString(); + if (error_string == NULL) + error_string = "attach failed"; + + SetExitStatus(-1, error_string); } } } @@ -3246,6 +3556,8 @@ Process::CompleteAttach () exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : ""); } } + + m_stop_info_override_callback = process_arch.GetStopInfoOverrideCallback(); } Error @@ -3823,26 +4135,25 @@ Process::StartPrivateStateThread (bool force) // events make it to clients (into the DCProcess event queue). char thread_name[1024]; - if (Host::MAX_THREAD_NAME_LENGTH <= 16) + if (HostInfo::GetMaxThreadNameLength() <= 30) { - // On platforms with abbreviated thread name lengths, choose thread names that fit within the limit. - if (already_running) - snprintf(thread_name, sizeof(thread_name), "intern-state-OV"); - else - snprintf(thread_name, sizeof(thread_name), "intern-state"); + // On platforms with abbreviated thread name lengths, choose thread names that fit within the limit. + if (already_running) + snprintf(thread_name, sizeof(thread_name), "intern-state-OV"); + else + snprintf(thread_name, sizeof(thread_name), "intern-state"); } else { if (already_running) - snprintf(thread_name, sizeof(thread_name), "", GetID()); + snprintf(thread_name, sizeof(thread_name), "", GetID()); else - snprintf(thread_name, sizeof(thread_name), "", GetID()); + snprintf(thread_name, sizeof(thread_name), "", GetID()); } // Create the private state thread, and start it running. - m_private_state_thread = Host::ThreadCreate (thread_name, Process::PrivateStateThread, this, NULL); - bool success = IS_VALID_LLDB_HOST_THREAD(m_private_state_thread); - if (success) + m_private_state_thread = ThreadLauncher::LaunchThread(thread_name, Process::PrivateStateThread, this, NULL); + if (m_private_state_thread.IsJoinable()) { ResumePrivateStateThread(); return true; @@ -3891,8 +4202,8 @@ Process::ControlPrivateStateThread (uint32_t signal) // Signal the private state thread. First we should copy this is case the // thread starts exiting since the private state thread will NULL this out // when it exits - const lldb::thread_t private_state_thread = m_private_state_thread; - if (IS_VALID_LLDB_HOST_THREAD(private_state_thread)) + HostThread private_state_thread(m_private_state_thread); + if (private_state_thread.IsJoinable()) { TimeValue timeout_time; bool timed_out; @@ -3910,8 +4221,7 @@ Process::ControlPrivateStateThread (uint32_t signal) { if (timed_out) { - Error error; - Host::ThreadCancel (private_state_thread, &error); + Error error = private_state_thread.Cancel(); if (log) log->Printf ("Timed out responding to the control event, cancel got error: \"%s\".", error.AsCString()); } @@ -3922,8 +4232,8 @@ Process::ControlPrivateStateThread (uint32_t signal) } thread_result_t result = NULL; - Host::ThreadJoin (private_state_thread, &result, NULL); - m_private_state_thread = LLDB_INVALID_HOST_THREAD; + private_state_thread.Join(&result); + m_private_state_thread.Reset(); } } else @@ -4005,7 +4315,8 @@ Process::HandlePrivateEvent (EventSP &event_sp) { // Only push the input handler if we aren't fowarding events, // as this means the curses GUI is in use... - if (!GetTarget().GetDebugger().IsForwardingEvents()) + // Or don't push it if we are launching since it will come up stopped. + if (!GetTarget().GetDebugger().IsForwardingEvents() && new_state != eStateLaunching) PushProcessIOHandler (); m_iohandler_sync.SetValue(true, eBroadcastAlways); } @@ -4167,7 +4478,7 @@ Process::RunPrivateStateThread () m_public_run_lock.SetStopped(); m_private_state_control_wait.SetValue (true, eBroadcastAlways); - m_private_state_thread = LLDB_INVALID_HOST_THREAD; + m_private_state_thread.Reset(); return NULL; } @@ -4621,7 +4932,7 @@ class IOHandlerProcessSTDIO : public: IOHandlerProcessSTDIO (Process *process, int write_fd) : - IOHandler(process->GetTarget().GetDebugger()), + IOHandler(process->GetTarget().GetDebugger(), IOHandler::Type::ProcessIO), m_process (process), m_read_file (), m_write_file (write_fd, false), @@ -4639,9 +4950,10 @@ public: bool OpenPipes () { - if (m_pipe.IsValid()) + if (m_pipe.CanRead() && m_pipe.CanWrite()) return true; - return m_pipe.Open(); + Error result = m_pipe.CreateNew(false); + return result.Success(); } void @@ -4702,8 +5014,10 @@ public: } if (FD_ISSET (pipe_read_fd, &read_fdset)) { + size_t bytes_read; // Consume the interrupt byte - if (m_pipe.Read (&ch, 1) == 1) + Error error = m_pipe.Read(&ch, 1, bytes_read); + if (error.Success()) { switch (ch) { @@ -4751,7 +5065,8 @@ public: Cancel () { char ch = 'q'; // Send 'q' for quit - m_pipe.Write (&ch, 1); + size_t bytes_written = 0; + m_pipe.Write(&ch, 1, bytes_written); } virtual bool @@ -4765,7 +5080,9 @@ public: if (m_active) { char ch = 'i'; // Send 'i' for interrupt - return m_pipe.Write (&ch, 1) == 1; + size_t bytes_written = 0; + Error result = m_pipe.Write(&ch, 1, bytes_written); + return result.Success(); } else { @@ -4944,12 +5261,12 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, selected_tid = LLDB_INVALID_THREAD_ID; } - lldb::thread_t backup_private_state_thread = LLDB_INVALID_HOST_THREAD; - lldb::StateType old_state; + HostThread backup_private_state_thread; + lldb::StateType old_state = eStateInvalid; lldb::ThreadPlanSP stopper_base_plan_sp; Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP | LIBLLDB_LOG_PROCESS)); - if (Host::GetCurrentThread() == m_private_state_thread) + if (m_private_state_thread.EqualsThread(Host::GetCurrentThread())) { // Yikes, we are running on the private state thread! So we can't wait for public events on this thread, since // we are the thread that is generating public events. @@ -5554,7 +5871,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, } // END WAIT LOOP // If we had to start up a temporary private state thread to run this thread plan, shut it down now. - if (IS_VALID_LLDB_HOST_THREAD(backup_private_state_thread)) + if (backup_private_state_thread.IsJoinable()) { StopPrivateStateThread(); Error error; @@ -5563,8 +5880,8 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, { thread->DiscardThreadPlansUpToPlan(stopper_base_plan_sp); } - m_public_state.SetValueNoLock(old_state); - + if (old_state != eStateInvalid) + m_public_state.SetValueNoLock(old_state); } // Restore the thread state if we are going to discard the plan execution. There are three cases where this @@ -5848,21 +6165,21 @@ Process::GetThreadStatus (Stream &strm, // ID's, and look them up one by one: uint32_t num_threads; - std::vector thread_index_array; + std::vector thread_id_array; //Scope for thread list locker; { Mutex::Locker locker (GetThreadList().GetMutex()); ThreadList &curr_thread_list = GetThreadList(); num_threads = curr_thread_list.GetSize(); uint32_t idx; - thread_index_array.resize(num_threads); + thread_id_array.resize(num_threads); for (idx = 0; idx < num_threads; ++idx) - thread_index_array[idx] = curr_thread_list.GetThreadAtIndex(idx)->GetID(); + thread_id_array[idx] = curr_thread_list.GetThreadAtIndex(idx)->GetID(); } for (uint32_t i = 0; i < num_threads; i++) { - ThreadSP thread_sp(GetThreadList().FindThreadByID(thread_index_array[i])); + ThreadSP thread_sp(GetThreadList().FindThreadByID(thread_id_array[i])); if (thread_sp) { if (only_threads_with_stop_reason) @@ -5915,7 +6232,8 @@ Process::RunPreResumeActions () struct PreResumeCallbackAndBaton action = m_pre_resume_actions.back(); m_pre_resume_actions.pop_back(); bool this_result = action.callback (action.baton); - if (result == true) result = this_result; + if (result == true) + result = this_result; } return result; } @@ -5955,8 +6273,10 @@ Process::DidExec () m_image_tokens.clear(); m_allocated_memory_cache.Clear(); m_language_runtimes.clear(); + m_instrumentation_runtimes.clear(); m_thread_list.DiscardThreadPlans(); m_memory_cache.Clear(true); + m_stop_info_override_callback = NULL; DoDidExec(); CompleteAttach (); // Flush the process (threads and all stack frames) after running CompleteAttach() @@ -6005,11 +6325,51 @@ Process::ResolveIndirectFunction(const Address *address, Error &error) void Process::ModulesDidLoad (ModuleList &module_list) { - SystemRuntime *sys_runtime = GetSystemRuntime(); - if (sys_runtime) - { - sys_runtime->ModulesDidLoad (module_list); - } + SystemRuntime *sys_runtime = GetSystemRuntime(); + if (sys_runtime) + { + sys_runtime->ModulesDidLoad (module_list); + } + + GetJITLoaders().ModulesDidLoad (module_list); + + // Give runtimes a chance to be created. + InstrumentationRuntime::ModulesDidLoad(module_list, this, m_instrumentation_runtimes); + + // Tell runtimes about new modules. + for (auto pos = m_instrumentation_runtimes.begin(); pos != m_instrumentation_runtimes.end(); ++pos) + { + InstrumentationRuntimeSP runtime = pos->second; + runtime->ModulesDidLoad(module_list); + } + +} + +ThreadCollectionSP +Process::GetHistoryThreads(lldb::addr_t addr) +{ + ThreadCollectionSP threads; + + const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(shared_from_this()); + + if (! memory_history.get()) { + return threads; + } + + threads.reset(new ThreadCollection(memory_history->GetHistoryThreads(addr))); + + return threads; +} - GetJITLoaders().ModulesDidLoad (module_list); +InstrumentationRuntimeSP +Process::GetInstrumentationRuntime(lldb::InstrumentationRuntimeType type) +{ + InstrumentationRuntimeCollection::iterator pos; + pos = m_instrumentation_runtimes.find (type); + if (pos == m_instrumentation_runtimes.end()) + { + return InstrumentationRuntimeSP(); + } + else + return (*pos).second; } diff --git a/source/Target/ProcessLaunchInfo.cpp b/source/Target/ProcessLaunchInfo.cpp index 830f1470ed98..451c42d18bfa 100644 --- a/source/Target/ProcessLaunchInfo.cpp +++ b/source/Target/ProcessLaunchInfo.cpp @@ -9,10 +9,8 @@ #include "lldb/Host/Config.h" -#ifndef LLDB_DISABLE_POSIX -#include -#endif - +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Log.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/Target.h" @@ -28,32 +26,32 @@ ProcessLaunchInfo::ProcessLaunchInfo () : ProcessInfo(), m_working_dir (), m_plugin_name (), - m_shell (), m_flags (0), m_file_actions (), - m_pty (), + m_pty (new lldb_utility::PseudoTerminal), m_resume_count (0), m_monitor_callback (NULL), m_monitor_callback_baton (NULL), m_monitor_signals (false), + m_listener_sp (), m_hijack_listener_sp () { } ProcessLaunchInfo::ProcessLaunchInfo(const char *stdin_path, const char *stdout_path, const char *stderr_path, - const char *working_directory, uint32_t launch_flags) - : ProcessInfo() - , m_working_dir() - , m_plugin_name() - , m_shell() - , m_flags(launch_flags) - , m_file_actions() - , m_pty() - , m_resume_count(0) - , m_monitor_callback(NULL) - , m_monitor_callback_baton(NULL) - , m_monitor_signals(false) - , m_hijack_listener_sp() + const char *working_directory, uint32_t launch_flags) : + ProcessInfo(), + m_working_dir(), + m_plugin_name(), + m_flags(launch_flags), + m_file_actions(), + m_pty(new lldb_utility::PseudoTerminal), + m_resume_count(0), + m_monitor_callback(NULL), + m_monitor_callback_baton(NULL), + m_monitor_signals(false), + m_listener_sp (), + m_hijack_listener_sp() { if (stdin_path) { @@ -184,27 +182,23 @@ ProcessLaunchInfo::SetProcessPluginName (const char *plugin) m_plugin_name.clear(); } -const char * +const FileSpec & ProcessLaunchInfo::GetShell () const { - if (m_shell.empty()) - return NULL; - return m_shell.c_str(); + return m_shell; } void -ProcessLaunchInfo::SetShell (const char * path) +ProcessLaunchInfo::SetShell (const FileSpec &shell) { - if (path && path[0]) + m_shell = shell; + if (m_shell) { - m_shell.assign (path); + m_shell.ResolveExecutableLocation(); m_flags.Set (lldb::eLaunchFlagLaunchInShell); } else - { - m_shell.clear(); m_flags.Clear (lldb::eLaunchFlagLaunchInShell); - } } void @@ -223,10 +217,11 @@ ProcessLaunchInfo::Clear () ProcessInfo::Clear(); m_working_dir.clear(); m_plugin_name.clear(); - m_shell.clear(); + m_shell.Clear(); m_flags.Clear(); m_file_actions.clear(); m_resume_count = 0; + m_listener_sp.reset(); m_hijack_listener_sp.reset(); } @@ -266,13 +261,23 @@ ProcessLaunchInfo::SetDetachOnError (bool enable) void ProcessLaunchInfo::FinalizeFileActions (Target *target, bool default_to_use_pty) { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); + // If nothing for stdin or stdout or stderr was specified, then check the process for any default // settings that were set with "settings set" - if (GetFileActionForFD(STDIN_FILENO) == NULL || GetFileActionForFD(STDOUT_FILENO) == NULL || + if (GetFileActionForFD(STDIN_FILENO) == NULL || + GetFileActionForFD(STDOUT_FILENO) == NULL || GetFileActionForFD(STDERR_FILENO) == NULL) { + if (log) + log->Printf ("ProcessLaunchInfo::%s at least one of stdin/stdout/stderr was not set, evaluating default handling", + __FUNCTION__); + if (m_flags.Test(eLaunchFlagDisableSTDIO)) { + if (log) + log->Printf ("ProcessLaunchInfo::%s eLaunchFlagDisableSTDIO set, adding suppression action for stdin, stdout and stderr", + __FUNCTION__); AppendSuppressFileAction (STDIN_FILENO , true, false); AppendSuppressFileAction (STDOUT_FILENO, false, true); AppendSuppressFileAction (STDERR_FILENO, false, true); @@ -288,34 +293,79 @@ ProcessLaunchInfo::FinalizeFileActions (Target *target, bool default_to_use_pty) FileSpec err_path; if (target) { - in_path = target->GetStandardInputPath(); - out_path = target->GetStandardOutputPath(); - err_path = target->GetStandardErrorPath(); + // Only override with the target settings if we don't already have + // an action for in, out or error + if (GetFileActionForFD(STDIN_FILENO) == NULL) + in_path = target->GetStandardInputPath(); + if (GetFileActionForFD(STDOUT_FILENO) == NULL) + out_path = target->GetStandardOutputPath(); + if (GetFileActionForFD(STDERR_FILENO) == NULL) + err_path = target->GetStandardErrorPath(); } + if (log) + log->Printf ("ProcessLaunchInfo::%s target stdin='%s', target stdout='%s', stderr='%s'", + __FUNCTION__, + in_path ? in_path.GetPath().c_str () : "", + out_path ? out_path.GetPath().c_str () : "", + err_path ? err_path.GetPath().c_str () : ""); + char path[PATH_MAX]; if (in_path && in_path.GetPath(path, sizeof(path))) + { AppendOpenFileAction(STDIN_FILENO, path, true, false); + if (log) + log->Printf ("ProcessLaunchInfo::%s appended stdin open file action for %s", + __FUNCTION__, + in_path.GetPath().c_str ()); + } if (out_path && out_path.GetPath(path, sizeof(path))) + { AppendOpenFileAction(STDOUT_FILENO, path, false, true); + if (log) + log->Printf ("ProcessLaunchInfo::%s appended stdout open file action for %s", + __FUNCTION__, + out_path.GetPath().c_str ()); + } if (err_path && err_path.GetPath(path, sizeof(path))) + { + if (log) + log->Printf ("ProcessLaunchInfo::%s appended stderr open file action for %s", + __FUNCTION__, + err_path.GetPath().c_str ()); AppendOpenFileAction(STDERR_FILENO, path, false, true); + } + + if (default_to_use_pty && (!in_path || !out_path || !err_path)) + { + if (log) + log->Printf ("ProcessLaunchInfo::%s default_to_use_pty is set, and at least one stdin/stderr/stdout is unset, so generating a pty to use for it", + __FUNCTION__); - if (default_to_use_pty && (!in_path || !out_path || !err_path)) { - if (m_pty.OpenFirstAvailableMaster(O_RDWR| O_NOCTTY, NULL, 0)) { - const char *slave_path = m_pty.GetSlaveName(NULL, 0); + if (m_pty->OpenFirstAvailableMaster(O_RDWR| O_NOCTTY, NULL, 0)) + { + const char *slave_path = m_pty->GetSlaveName(NULL, 0); - if (!in_path) { + // Only use the slave tty if we don't have anything specified for + // input and don't have an action for stdin + if (!in_path && GetFileActionForFD(STDIN_FILENO) == NULL) + { AppendOpenFileAction(STDIN_FILENO, slave_path, true, false); } - if (!out_path) { + // Only use the slave tty if we don't have anything specified for + // output and don't have an action for stdout + if (!out_path && GetFileActionForFD(STDOUT_FILENO) == NULL) + { AppendOpenFileAction(STDOUT_FILENO, slave_path, false, true); } - if (!err_path) { + // Only use the slave tty if we don't have anything specified for + // error and don't have an action for stderr + if (!err_path && GetFileActionForFD(STDERR_FILENO) == NULL) + { AppendOpenFileAction(STDERR_FILENO, slave_path, false, true); } } @@ -336,42 +386,30 @@ ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell (Error &error, if (GetFlags().Test (eLaunchFlagLaunchInShell)) { - const char *shell_executable = GetShell(); - if (shell_executable) + if (m_shell) { - char shell_resolved_path[PATH_MAX]; - - if (localhost) - { - FileSpec shell_filespec (shell_executable, true); - - if (!shell_filespec.Exists()) - { - // Resolve the path in case we just got "bash", "sh" or "tcsh" - if (!shell_filespec.ResolveExecutableLocation ()) - { - error.SetErrorStringWithFormat("invalid shell path '%s'", shell_executable); - return false; - } - } - shell_filespec.GetPath (shell_resolved_path, sizeof(shell_resolved_path)); - shell_executable = shell_resolved_path; - } + std::string shell_executable = m_shell.GetPath(); const char **argv = GetArguments().GetConstArgumentVector (); if (argv == NULL || argv[0] == NULL) return false; Args shell_arguments; std::string safe_arg; - shell_arguments.AppendArgument (shell_executable); - shell_arguments.AppendArgument ("-c"); + shell_arguments.AppendArgument (shell_executable.c_str()); + const llvm::Triple &triple = GetArchitecture().GetTriple(); + if (triple.getOS() == llvm::Triple::Win32 && !triple.isWindowsCygwinEnvironment()) + shell_arguments.AppendArgument("/C"); + else + shell_arguments.AppendArgument("-c"); + StreamString shell_command; if (will_debug) { // Add a modified PATH environment variable in case argv[0] - // is a relative path + // is a relative path. const char *argv0 = argv[0]; - if (argv0 && (argv0[0] != '/' && argv0[0] != '~')) + FileSpec arg_spec(argv0, false); + if (arg_spec.IsRelativeToCurrentWorkingDirectory()) { // We have a relative path to our executable which may not work if // we just try to run "a.out" (without it being converted to "./a.out") @@ -402,7 +440,8 @@ ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell (Error &error, shell_command.PutCString(new_path.c_str()); } - shell_command.PutCString ("exec"); + if (triple.getOS() != llvm::Triple::Win32 || triple.isWindowsCygwinEnvironment()) + shell_command.PutCString("exec"); // Only Apple supports /usr/bin/arch being able to specify the architecture if (GetArchitecture().IsValid() && // Valid architecture @@ -442,7 +481,7 @@ ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell (Error &error, } } shell_arguments.AppendArgument (shell_command.GetString().c_str()); - m_executable.SetFile(shell_executable, false); + m_executable = m_shell; m_arguments = shell_arguments; return true; } @@ -457,3 +496,12 @@ ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell (Error &error, } return false; } + +Listener & +ProcessLaunchInfo::GetListenerForProcess (Debugger &debugger) +{ + if (m_listener_sp) + return *m_listener_sp; + else + return debugger.GetListener(); +} diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp index e497b176ccfe..c46db4cfadf9 100644 --- a/source/Target/StackFrame.cpp +++ b/source/Target/StackFrame.cpp @@ -70,7 +70,8 @@ StackFrame::StackFrame (const ThreadSP &thread_sp, m_is_history_frame (is_history_frame), m_variable_list_sp (), m_variable_list_value_objects (), - m_disassembly () + m_disassembly (), + m_mutex (Mutex::eMutexTypeRecursive) { // If we don't have a CFA value, use the frame index for our StackID so that recursive // functions properly aren't confused with one another on a history stack. @@ -109,7 +110,8 @@ StackFrame::StackFrame (const ThreadSP &thread_sp, m_is_history_frame (false), m_variable_list_sp (), m_variable_list_value_objects (), - m_disassembly () + m_disassembly (), + m_mutex (Mutex::eMutexTypeRecursive) { if (sc_ptr != NULL) { @@ -148,7 +150,8 @@ StackFrame::StackFrame (const ThreadSP &thread_sp, m_is_history_frame (false), m_variable_list_sp (), m_variable_list_value_objects (), - m_disassembly () + m_disassembly (), + m_mutex (Mutex::eMutexTypeRecursive) { if (sc_ptr != NULL) { @@ -189,6 +192,7 @@ StackFrame::~StackFrame() StackID& StackFrame::GetStackID() { + Mutex::Locker locker(m_mutex); // Make sure we have resolved the StackID object's symbol context scope if // we already haven't looked it up. @@ -235,6 +239,7 @@ StackFrame::GetFrameIndex () const void StackFrame::SetSymbolContextScope (SymbolContextScope *symbol_scope) { + Mutex::Locker locker(m_mutex); m_flags.Set (RESOLVED_FRAME_ID_SYMBOL_SCOPE); m_id.SetSymbolContextScope (symbol_scope); } @@ -242,6 +247,7 @@ StackFrame::SetSymbolContextScope (SymbolContextScope *symbol_scope) const Address& StackFrame::GetFrameCodeAddress() { + Mutex::Locker locker(m_mutex); if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) && !m_frame_code_addr.IsSectionOffset()) { m_flags.Set (RESOLVED_FRAME_CODE_ADDR); @@ -272,6 +278,7 @@ StackFrame::GetFrameCodeAddress() bool StackFrame::ChangePC (addr_t pc) { + Mutex::Locker locker(m_mutex); // We can't change the pc value of a history stack frame - it is immutable. if (m_is_history_frame) return false; @@ -287,6 +294,7 @@ StackFrame::ChangePC (addr_t pc) const char * StackFrame::Disassemble () { + Mutex::Locker locker(m_mutex); if (m_disassembly.GetSize() == 0) { ExecutionContext exe_ctx (shared_from_this()); @@ -346,6 +354,7 @@ StackFrame::GetFrameBlock () const SymbolContext& StackFrame::GetSymbolContext (uint32_t resolve_scope) { + Mutex::Locker locker(m_mutex); // Copy our internal symbol context into "sc". if ((m_flags.Get() & resolve_scope) != resolve_scope) { @@ -375,7 +384,31 @@ StackFrame::GetSymbolContext (uint32_t resolve_scope) { 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); + } + } + } } @@ -504,6 +537,7 @@ StackFrame::GetSymbolContext (uint32_t resolve_scope) VariableList * StackFrame::GetVariableList (bool get_file_globals) { + Mutex::Locker locker(m_mutex); if (m_flags.IsClear(RESOLVED_VARIABLES)) { m_flags.Set(RESOLVED_VARIABLES); @@ -544,6 +578,7 @@ StackFrame::GetVariableList (bool get_file_globals) VariableListSP StackFrame::GetInScopeVariableList (bool get_file_globals) { + Mutex::Locker locker(m_mutex); // We can't fetch variable information for a history stack frame. if (m_is_history_frame) return VariableListSP(); @@ -680,8 +715,8 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr, // Make sure we aren't trying to deref an objective // C ivar if this is not allowed const uint32_t pointer_type_flags = valobj_sp->GetClangType().GetTypeInfo (NULL); - if ((pointer_type_flags & ClangASTType::eTypeIsObjC) && - (pointer_type_flags & ClangASTType::eTypeIsPointer)) + if ((pointer_type_flags & eTypeIsObjC) && + (pointer_type_flags & eTypeIsPointer)) { // This was an objective C object pointer and // it was requested we skip any fragile ivars @@ -1142,6 +1177,7 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr, bool StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr) { + Mutex::Locker locker(m_mutex); if (m_cfa_is_valid == false) { m_frame_base_error.SetErrorString("No frame base available for this historical stack frame."); @@ -1191,6 +1227,7 @@ StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr) RegisterContextSP StackFrame::GetRegisterContext () { + Mutex::Locker locker(m_mutex); if (!m_reg_context_sp) { ThreadSP thread_sp (GetThread()); @@ -1211,6 +1248,7 @@ StackFrame::HasDebugInformation () ValueObjectSP StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic) { + Mutex::Locker locker(m_mutex); ValueObjectSP valobj_sp; if (m_is_history_frame) { @@ -1246,6 +1284,7 @@ StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp, Dynam ValueObjectSP StackFrame::TrackGlobalVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic) { + Mutex::Locker locker(m_mutex); if (m_is_history_frame) return ValueObjectSP(); @@ -1365,17 +1404,20 @@ StackFrame::Dump (Stream *strm, bool show_frame_index, bool show_fullpaths) GetSymbolContext(eSymbolContextEverything); const bool show_module = true; const bool show_inline = true; + const bool show_function_arguments = true; m_sc.DumpStopContext (strm, exe_ctx.GetBestExecutionContextScope(), GetFrameCodeAddress(), show_fullpaths, show_module, - show_inline); + show_inline, + show_function_arguments); } void StackFrame::UpdateCurrentFrameFromPreviousFrame (StackFrame &prev_frame) { + Mutex::Locker locker(m_mutex); assert (GetStackID() == prev_frame.GetStackID()); // TODO: remove this after some testing m_variable_list_sp = prev_frame.m_variable_list_sp; m_variable_list_value_objects.Swap (prev_frame.m_variable_list_value_objects); @@ -1387,6 +1429,7 @@ StackFrame::UpdateCurrentFrameFromPreviousFrame (StackFrame &prev_frame) void StackFrame::UpdatePreviousFrameFromCurrentFrame (StackFrame &curr_frame) { + Mutex::Locker locker(m_mutex); assert (GetStackID() == curr_frame.GetStackID()); // TODO: remove this after some testing m_id.SetPC (curr_frame.m_id.GetPC()); // Update the Stack ID PC value assert (GetThread() == curr_frame.GetThread()); diff --git a/source/Target/StackFrameList.cpp b/source/Target/StackFrameList.cpp index 99234dc61f1d..9a132618288d 100644 --- a/source/Target/StackFrameList.cpp +++ b/source/Target/StackFrameList.cpp @@ -288,8 +288,8 @@ StackFrameList::GetFramesUpTo(uint32_t end_idx) do { uint32_t idx = m_concrete_frames_fetched++; - lldb::addr_t pc; - lldb::addr_t cfa; + lldb::addr_t pc = LLDB_INVALID_ADDRESS; + lldb::addr_t cfa = LLDB_INVALID_ADDRESS; if (idx == 0) { // We might have already created frame zero, only create it @@ -625,11 +625,14 @@ StackFrameList::GetFrameWithStackID (const StackID &stack_id) if (begin != end) { collection::const_iterator pos = std::lower_bound (begin, end, stack_id, CompareStackID); - if (pos != end && (*pos)->GetStackID() == stack_id) - return *pos; + if (pos != end) + { + if ((*pos)->GetStackID() == stack_id) + return *pos; + } - if (m_frames.back()->GetStackID() < stack_id) - frame_idx = m_frames.size(); +// if (m_frames.back()->GetStackID() < stack_id) +// frame_idx = m_frames.size(); } do { diff --git a/source/Target/StopInfo.cpp b/source/Target/StopInfo.cpp index a37a4079ff11..4b57ca65a2df 100644 --- a/source/Target/StopInfo.cpp +++ b/source/Target/StopInfo.cpp @@ -40,7 +40,8 @@ StopInfo::StopInfo (Thread &thread, uint64_t value) : m_resume_id (thread.GetProcess()->GetResumeID()), m_value (value), m_override_should_notify (eLazyBoolCalculate), - m_override_should_stop (eLazyBoolCalculate) + m_override_should_stop (eLazyBoolCalculate), + m_extended_info() { } @@ -181,6 +182,7 @@ public: { ExecutionContext exe_ctx (thread_sp->GetStackFrameAtIndex(0)); StoppointCallbackContext context (event_ptr, exe_ctx, true); + bp_site_sp->BumpHitCounts(); m_should_stop = bp_site_sp->ShouldStop (&context); } else @@ -402,10 +404,21 @@ protected: // Let's copy the breakpoint locations out of the site and store them in a local list. That way if // one of the breakpoint actions changes the site, then we won't be operating on a bad list. + // For safety's sake let's also grab an extra reference to the breakpoint owners of the locations we're + // going to examine, since the locations are going to have to get back to their breakpoints, and the + // locations don't keep their owners alive. I'm just sticking the BreakpointSP's in a vector since + // I'm only really using it to locally increment their retain counts. BreakpointLocationCollection site_locations; + std::vector location_owners; + for (size_t j = 0; j < num_owners; j++) - site_locations.Add(bp_site_sp->GetOwnerAtIndex(j)); + { + BreakpointLocationSP loc(bp_site_sp->GetOwnerAtIndex(j)); + site_locations.Add(loc); + location_owners.push_back(loc->GetBreakpoint().shared_from_this()); + + } for (size_t j = 0; j < num_owners; j++) { @@ -689,14 +702,13 @@ protected: assert (stored_stop_info_sp.get() == this); ThreadPlanSP new_plan_sp(thread_sp->QueueThreadPlanForStepSingleInstruction(false, // step-over - false, // abort_other_plans - true)); // stop_other_threads + false, // abort_other_plans + true)); // stop_other_threads new_plan_sp->SetIsMasterPlan (true); new_plan_sp->SetOkayToDiscard (false); new_plan_sp->SetPrivate (true); process->GetThreadList().SetSelectedThreadByID (thread_sp->GetID()); - process->Resume (); - process->WaitForProcessToStop (NULL); + process->ResumeSynchronous(NULL); process->GetThreadList().SetSelectedThreadByID (thread_sp->GetID()); thread_sp->SetStopInfo(stored_stop_info_sp); } diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp index d2d0b5098555..e9393d1be0b4 100644 --- a/source/Target/Target.cpp +++ b/source/Target/Target.cpp @@ -35,6 +35,7 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Expression/ClangASTSource.h" #include "lldb/Expression/ClangUserExpression.h" +#include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -63,7 +64,7 @@ Target::GetStaticBroadcasterClass () //---------------------------------------------------------------------- // Target constructor //---------------------------------------------------------------------- -Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::PlatformSP &platform_sp) : +Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::PlatformSP &platform_sp, bool is_dummy_target) : TargetProperties (this), Broadcaster (&debugger, Target::GetStaticBroadcasterClass().AsCString()), ExecutionContextScope (), @@ -87,7 +88,9 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat m_stop_hooks (), m_stop_hook_next_id (0), m_valid (true), - m_suppress_stop_hooks (false) + m_suppress_stop_hooks (false), + m_is_dummy_target(is_dummy_target) + { SetEventName (eBroadcastBitBreakpointChanged, "breakpoint-changed"); SetEventName (eBroadcastBitModulesLoaded, "modules-loaded"); @@ -106,6 +109,24 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat } } +void +Target::PrimeFromDummyTarget(Target *target) +{ + if (!target) + return; + + m_stop_hooks = target->m_stop_hooks; + + for (BreakpointSP breakpoint_sp : target->m_breakpoint_list.Breakpoints()) + { + if (breakpoint_sp->IsInternal()) + continue; + + BreakpointSP new_bp (new Breakpoint (*this, *breakpoint_sp.get())); + AddBreakpoint (new_bp, false); + } +} + //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- @@ -330,7 +351,7 @@ Target::CreateBreakpoint (lldb::addr_t addr, bool internal, bool hardware) BreakpointSP Target::CreateBreakpoint (Address &addr, bool internal, bool hardware) { - SearchFilterSP filter_sp(new SearchFilterForNonModuleSpecificSearches (shared_from_this())); + SearchFilterSP filter_sp(new SearchFilterForUnconstrainedSearches (shared_from_this())); BreakpointResolverSP resolver_sp (new BreakpointResolverAddress (NULL, addr)); return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, false); } @@ -430,7 +451,7 @@ Target::GetSearchFilterForModule (const FileSpec *containingModule) else { if (m_search_filter_sp.get() == NULL) - m_search_filter_sp.reset (new SearchFilterForNonModuleSpecificSearches (shared_from_this())); + m_search_filter_sp.reset (new SearchFilterForUnconstrainedSearches (shared_from_this())); filter_sp = m_search_filter_sp; } return filter_sp; @@ -449,7 +470,7 @@ Target::GetSearchFilterForModuleList (const FileSpecList *containingModules) else { if (m_search_filter_sp.get() == NULL) - m_search_filter_sp.reset (new SearchFilterForNonModuleSpecificSearches (shared_from_this())); + m_search_filter_sp.reset (new SearchFilterForUnconstrainedSearches (shared_from_this())); filter_sp = m_search_filter_sp; } return filter_sp; @@ -510,29 +531,35 @@ Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resol { bp_sp.reset(new Breakpoint (*this, filter_sp, resolver_sp, request_hardware, resolve_indirect_symbols)); resolver_sp->SetBreakpoint (bp_sp.get()); + AddBreakpoint (bp_sp, internal); + } + return bp_sp; +} - if (internal) - m_internal_breakpoint_list.Add (bp_sp, false); - else - m_breakpoint_list.Add (bp_sp, true); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - { - StreamString s; - bp_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); - log->Printf ("Target::%s (internal = %s) => break_id = %s\n", __FUNCTION__, internal ? "yes" : "no", s.GetData()); - } +void +Target::AddBreakpoint (lldb::BreakpointSP bp_sp, bool internal) +{ + if (!bp_sp) + return; + if (internal) + m_internal_breakpoint_list.Add (bp_sp, false); + else + m_breakpoint_list.Add (bp_sp, true); - bp_sp->ResolveBreakpoint(); + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + if (log) + { + StreamString s; + bp_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); + log->Printf ("Target::%s (internal = %s) => break_id = %s\n", __FUNCTION__, bp_sp->IsInternal() ? "yes" : "no", s.GetData()); } - - if (!internal && bp_sp) + + bp_sp->ResolveBreakpoint(); + + if (!internal) { m_last_created_breakpoint = bp_sp; } - - return bp_sp; } bool @@ -1214,6 +1241,7 @@ Target::ModulesDidUnload (ModuleList &module_list, bool delete_locations) { if (m_valid && module_list.GetSize()) { + UnloadModuleSections (module_list); m_breakpoint_list.UpdateBreakpoints (module_list, false, delete_locations); // TODO: make event data that packages up the module_list BroadcastEvent (eBroadcastBitModulesUnloaded, NULL); @@ -1221,7 +1249,7 @@ Target::ModulesDidUnload (ModuleList &module_list, bool delete_locations) } bool -Target::ModuleIsExcludedForNonModuleSpecificSearches (const FileSpec &module_file_spec) +Target::ModuleIsExcludedForUnconstrainedSearches (const FileSpec &module_file_spec) { if (GetBreakpointsConsultPlatformAvoidList()) { @@ -1235,7 +1263,7 @@ Target::ModuleIsExcludedForNonModuleSpecificSearches (const FileSpec &module_fil { for (size_t i = 0; i < num_modules; i++) { - if (!ModuleIsExcludedForNonModuleSpecificSearches (matchingModules.GetModuleAtIndex(i))) + if (!ModuleIsExcludedForUnconstrainedSearches (matchingModules.GetModuleAtIndex(i))) return false; } return true; @@ -1245,12 +1273,12 @@ Target::ModuleIsExcludedForNonModuleSpecificSearches (const FileSpec &module_fil } bool -Target::ModuleIsExcludedForNonModuleSpecificSearches (const lldb::ModuleSP &module_sp) +Target::ModuleIsExcludedForUnconstrainedSearches (const lldb::ModuleSP &module_sp) { if (GetBreakpointsConsultPlatformAvoidList()) { if (m_platform_sp) - return m_platform_sp->ModuleIsExcludedForNonModuleSpecificSearches (*this, module_sp); + return m_platform_sp->ModuleIsExcludedForUnconstrainedSearches (*this, module_sp); } return false; } @@ -1355,9 +1383,9 @@ Target::ReadMemory (const Address& addr, ModuleSP addr_module_sp (resolved_addr.GetModule()); if (addr_module_sp && addr_module_sp->GetFileSpec()) error.SetErrorStringWithFormat("%s[0x%" PRIx64 "] can't be resolved, %s in not currently loaded", - addr_module_sp->GetFileSpec().GetFilename().AsCString(), + addr_module_sp->GetFileSpec().GetFilename().AsCString(""), resolved_addr.GetFileAddress(), - addr_module_sp->GetFileSpec().GetFilename().AsCString()); + addr_module_sp->GetFileSpec().GetFilename().AsCString("")); else error.SetErrorStringWithFormat("0x%" PRIx64 " can't be resolved", resolved_addr.GetFileAddress()); } @@ -1436,7 +1464,12 @@ Target::ReadCStringFromMemory (const Address& addr, char *dst, size_t dst_max_le Error error; addr_t curr_addr = addr.GetLoadAddress(this); Address address(addr); + + // We could call m_process_sp->GetMemoryCacheLineSize() but I don't + // think this really needs to be tied to the memory cache subsystem's + // cache line size, so leave this as a fixed constant. const size_t cache_line_size = 512; + size_t bytes_left = dst_max_len - 1; char *curr_dst = dst; @@ -2006,6 +2039,22 @@ Target::GetSourceManager () return *m_source_manager_ap; } +ClangModulesDeclVendor * +Target::GetClangModulesDeclVendor () +{ + static Mutex s_clang_modules_decl_vendor_mutex; // If this is contended we can make it per-target + + { + Mutex::Locker clang_modules_decl_vendor_locker(s_clang_modules_decl_vendor_mutex); + + if (!m_clang_modules_decl_vendor_ap) + { + m_clang_modules_decl_vendor_ap.reset(ClangModulesDeclVendor::Create(*this)); + } + } + + return m_clang_modules_decl_vendor_ap.get(); +} Target::StopHookSP Target::CreateStopHook () @@ -2173,18 +2222,17 @@ Target::RunStopHooks () if (print_thread_header) result.AppendMessageWithFormat("-- Thread %d\n", exc_ctx_with_reasons[i].GetThreadPtr()->GetIndexID()); - - bool stop_on_continue = true; - bool stop_on_error = true; - bool echo_commands = false; - bool print_results = true; - GetDebugger().GetCommandInterpreter().HandleCommands (cur_hook_sp->GetCommands(), - &exc_ctx_with_reasons[i], - stop_on_continue, - stop_on_error, - echo_commands, - print_results, - eLazyBoolNo, + + CommandInterpreterRunOptions options; + options.SetStopOnContinue (true); + options.SetStopOnError (true); + options.SetEchoCommands (false); + options.SetPrintResults (true); + options.SetAddToHistory (false); + + GetDebugger().GetCommandInterpreter().HandleCommands (cur_hook_sp->GetCommands(), + &exc_ctx_with_reasons[i], + options, result); // If the command started the target going again, we should bag out of @@ -2278,6 +2326,12 @@ Target::ResolveLoadAddress (addr_t load_addr, Address &so_addr, uint32_t stop_id return m_section_load_history.ResolveLoadAddress(stop_id, load_addr, so_addr); } +bool +Target::ResolveFileAddress (lldb::addr_t file_addr, Address &resolved_addr) +{ + return m_images.ResolveFileAddress(file_addr, resolved_addr); +} + bool Target::SetSectionLoadAddress (const SectionSP §ion_sp, addr_t new_section_load_addr, bool warn_multiple) { @@ -2297,6 +2351,40 @@ Target::SetSectionLoadAddress (const SectionSP §ion_sp, addr_t new_section_l } +size_t +Target::UnloadModuleSections (const ModuleList &module_list) +{ + size_t section_unload_count = 0; + size_t num_modules = module_list.GetSize(); + for (size_t i=0; iGetStopID(); + else + stop_id = m_section_load_history.GetLastStopID(); + SectionList *sections = module_sp->GetSectionList(); + size_t section_unload_count = 0; + if (sections) + { + const uint32_t num_sections = sections->GetNumSections(0); + for (uint32_t i = 0; i < num_sections; ++i) + { + section_unload_count += m_section_load_history.SetSectionUnloaded(stop_id, sections->GetSectionAtIndex(i)); + } + } + return section_unload_count; +} + bool Target::SetSectionUnloaded (const lldb::SectionSP §ion_sp) { @@ -2329,10 +2417,14 @@ Target::ClearAllLoadedSections () Error -Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info) +Target::Launch (ProcessLaunchInfo &launch_info, Stream *stream) { Error error; - + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TARGET)); + + if (log) + log->Printf ("Target::%s() called for %s", __FUNCTION__, launch_info.GetExecutableFile().GetPath().c_str ()); + StateType state = eStateInvalid; // Scope to temporarily get the process state in case someone has manually @@ -2342,7 +2434,16 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info) ProcessSP process_sp (GetProcessSP()); if (process_sp) + { state = process_sp->GetState(); + if (log) + log->Printf ("Target::%s the process exists, and its current state is %s", __FUNCTION__, StateAsCString (state)); + } + else + { + if (log) + log->Printf ("Target::%s the process instance doesn't currently exist.", __FUNCTION__); + } } launch_info.GetFlags().Set (eLaunchFlagDebug); @@ -2358,6 +2459,13 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info) // Finalize the file actions, and if none were given, default to opening // up a pseudo terminal const bool default_to_use_pty = platform_sp ? platform_sp->IsHost() : false; + if (log) + log->Printf ("Target::%s have platform=%s, platform_sp->IsHost()=%s, default_to_use_pty=%s", + __FUNCTION__, + platform_sp ? "true" : "false", + platform_sp ? (platform_sp->IsHost () ? "true" : "false") : "n/a", + default_to_use_pty ? "true" : "false"); + launch_info.FinalizeFileActions (this, default_to_use_pty); if (state == eStateConnected) @@ -2375,14 +2483,19 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info) // 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 ()) { + if (log) + log->Printf ("Target::%s asking the platform to debug the process", __FUNCTION__); + m_process_sp = GetPlatform()->DebugProcess (launch_info, debugger, this, - listener, error); } else { + if (log) + log->Printf ("Target::%s the platform doesn't know how to debug a process, getting a process plugin to do this for us.", __FUNCTION__); + if (state == eStateConnected) { assert(m_process_sp); @@ -2391,7 +2504,7 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info) { // Use a Process plugin to construct the process. const char *plugin_name = launch_info.GetProcessPluginName(); - CreateProcess (listener, plugin_name, NULL); + CreateProcess (launch_info.GetListenerForProcess(debugger), plugin_name, NULL); } // Since we didn't have a platform launch the process, launch it here. @@ -2411,8 +2524,8 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info) if (launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false) { ListenerSP hijack_listener_sp (launch_info.GetHijackListener()); - - StateType state = m_process_sp->WaitForProcessToStop (NULL, NULL, false, hijack_listener_sp.get()); + + StateType state = m_process_sp->WaitForProcessToStop (NULL, NULL, false, hijack_listener_sp.get(), NULL); if (state == eStateStopped) { @@ -2430,7 +2543,7 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info) if (synchronous_execution) { - state = m_process_sp->WaitForProcessToStop (NULL, NULL, true, hijack_listener_sp.get()); + state = m_process_sp->WaitForProcessToStop (NULL, NULL, true, hijack_listener_sp.get(), stream); const bool must_be_alive = false; // eStateExited is ok, so this must be false if (!StateIsStoppedState(state, must_be_alive)) { @@ -2447,7 +2560,7 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info) } else if (state == eStateExited) { - bool with_shell = launch_info.GetShell(); + bool with_shell = !!launch_info.GetShell(); const int exit_status = m_process_sp->GetExitStatus(); const char *exit_desc = m_process_sp->GetExitDescription(); #define LAUNCH_SHELL_MESSAGE "\n'r' and 'run' are aliases that default to launching through a shell.\nTry launching without going through a shell by using 'process launch'." @@ -2632,7 +2745,7 @@ g_properties[] = { { "default-arch" , OptionValue::eTypeArch , true , 0 , NULL, NULL, "Default architecture to choose, when there's a choice." }, { "expr-prefix" , OptionValue::eTypeFileSpec , false, 0 , NULL, NULL, "Path to a file containing expressions to be prepended to all expressions." }, - { "prefer-dynamic-value" , OptionValue::eTypeEnum , false, eNoDynamicValues , NULL, g_dynamic_value_types, "Should printed values be shown as their dynamic value." }, + { "prefer-dynamic-value" , OptionValue::eTypeEnum , false, eDynamicDontRunTarget , NULL, g_dynamic_value_types, "Should printed values be shown as their dynamic value." }, { "enable-synthetic-value" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "Should synthetic values be used by default whenever available." }, { "skip-prologue" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "Skip function prologues when setting breakpoints by name." }, { "source-map" , OptionValue::eTypePathMap , false, 0 , NULL, NULL, "Source path remappings used to track the change of location between a source file when built, and " @@ -2656,12 +2769,13 @@ g_properties[] = { "detach-on-error" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "debugserver will detach (rather than killing) a process if it loses connection with lldb." }, { "disable-aslr" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "Disable Address Space Layout Randomization (ASLR)" }, { "disable-stdio" , OptionValue::eTypeBoolean , false, false , NULL, NULL, "Disable stdin/stdout for process (e.g. for a GUI application)" }, - { "inline-breakpoint-strategy" , OptionValue::eTypeEnum , false, eInlineBreakpointsHeaders , NULL, g_inline_breakpoint_enums, "The strategy to use when settings breakpoints by file and line. " + { "inline-breakpoint-strategy" , OptionValue::eTypeEnum , false, eInlineBreakpointsAlways , NULL, g_inline_breakpoint_enums, "The strategy to use when settings breakpoints by file and line. " "Breakpoint locations can end up being inlined by the compiler, so that a compile unit 'a.c' might contain an inlined function from another source file. " "Usually this is limitted to breakpoint locations from inlined functions from header or other include files, or more accurately non-implementation source files. " "Sometimes code might #include implementation files and cause inlined breakpoint locations in inlined implementation files. " - "Always checking for inlined breakpoint locations can be expensive (memory and time), so we try to minimize the " - "times we look for inlined locations. This setting allows you to control exactly which strategy is used when settings " + "Always checking for inlined breakpoint locations can be expensive (memory and time), so if you have a project with many headers " + "and find that setting breakpoints is slow, then you can change this setting to headers. " + "This setting allows you to control exactly which strategy is used when setting " "file and line breakpoints." }, // FIXME: This is the wrong way to do per-architecture settings, but we don't have a general per architecture settings system in place yet. { "x86-disassembly-flavor" , OptionValue::eTypeEnum , false, eX86DisFlavorDefault, NULL, g_x86_dis_flavor_value_types, "The default disassembly flavor to use for x86 or x86-64 targets." }, diff --git a/source/Target/TargetList.cpp b/source/Target/TargetList.cpp index 5ee75ff74449..28ad47e3d81d 100644 --- a/source/Target/TargetList.cpp +++ b/source/Target/TargetList.cpp @@ -21,6 +21,7 @@ #include "lldb/Core/State.h" #include "lldb/Core/Timer.h" #include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/OptionGroupPlatform.h" #include "lldb/Symbol/ObjectFile.h" @@ -68,6 +69,41 @@ TargetList::CreateTarget (Debugger &debugger, bool get_dependent_files, const OptionGroupPlatform *platform_options, TargetSP &target_sp) +{ + return CreateTargetInternal (debugger, + user_exe_path, + triple_cstr, + get_dependent_files, + platform_options, + target_sp, + false); +} + +Error +TargetList::CreateTarget (Debugger &debugger, + const char *user_exe_path, + const ArchSpec& specified_arch, + bool get_dependent_files, + PlatformSP &platform_sp, + TargetSP &target_sp) +{ + return CreateTargetInternal (debugger, + user_exe_path, + specified_arch, + get_dependent_files, + platform_sp, + target_sp, + false); +} + +Error +TargetList::CreateTargetInternal (Debugger &debugger, + const char *user_exe_path, + const char *triple_cstr, + bool get_dependent_files, + const OptionGroupPlatform *platform_options, + TargetSP &target_sp, + bool is_dummy_target) { Error error; PlatformSP platform_sp; @@ -170,7 +206,7 @@ TargetList::CreateTarget (Debugger &debugger, typedef std::vector PlatformList; PlatformList platforms; - PlatformSP host_platform_sp = Platform::GetDefaultPlatform(); + PlatformSP host_platform_sp = Platform::GetHostPlatform(); for (size_t i=0; iIsCompatibleArchitecture(arch, false, &platform_arch)) + { platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch); + if (platform_sp) + debugger.GetPlatformList().SetSelectedPlatform(platform_sp); + } } else if (platform_arch.IsValid()) { @@ -266,30 +306,69 @@ TargetList::CreateTarget (Debugger &debugger, // a single architecture which should be used ArchSpec fixed_platform_arch; if (!platform_sp->IsCompatibleArchitecture(platform_arch, false, &fixed_platform_arch)) + { platform_sp = Platform::GetPlatformForArchitecture(platform_arch, &fixed_platform_arch); + if (platform_sp) + debugger.GetPlatformList().SetSelectedPlatform(platform_sp); + } } } if (!platform_arch.IsValid()) platform_arch = arch; - error = TargetList::CreateTarget (debugger, - user_exe_path, - platform_arch, - get_dependent_files, - platform_sp, - target_sp); + error = TargetList::CreateTargetInternal (debugger, + user_exe_path, + platform_arch, + get_dependent_files, + platform_sp, + target_sp, + is_dummy_target); return error; } +lldb::TargetSP +TargetList::GetDummyTarget (lldb_private::Debugger &debugger) +{ + // FIXME: Maybe the dummy target should be per-Debugger + if (!m_dummy_target_sp || !m_dummy_target_sp->IsValid()) + { + ArchSpec arch(Target::GetDefaultArchitecture()); + if (!arch.IsValid()) + arch = HostInfo::GetArchitecture(); + Error err = CreateDummyTarget(debugger, + arch.GetTriple().getTriple().c_str(), + m_dummy_target_sp); + } + + return m_dummy_target_sp; +} + Error -TargetList::CreateTarget (Debugger &debugger, - const char *user_exe_path, - const ArchSpec& specified_arch, - bool get_dependent_files, - PlatformSP &platform_sp, - TargetSP &target_sp) +TargetList::CreateDummyTarget (Debugger &debugger, + const char *specified_arch_name, + lldb::TargetSP &target_sp) { + PlatformSP host_platform_sp(Platform::GetHostPlatform()); + return CreateTargetInternal (debugger, + (const char *) nullptr, + specified_arch_name, + false, + (const OptionGroupPlatform *) nullptr, + target_sp, + true); +} + +Error +TargetList::CreateTargetInternal (Debugger &debugger, + const char *user_exe_path, + const ArchSpec& specified_arch, + bool get_dependent_files, + lldb::PlatformSP &platform_sp, + lldb::TargetSP &target_sp, + bool is_dummy_target) +{ + Timer scoped_timer (__PRETTY_FUNCTION__, "TargetList::CreateTarget (file = '%s', arch = '%s')", user_exe_path, @@ -332,7 +411,7 @@ TargetList::CreateTarget (Debugger &debugger, if (file.GetFileType() == FileSpec::eFileTypeDirectory) user_exe_path_is_bundle = true; - if (file.IsRelativeToCurrentWorkingDirectory()) + if (file.IsRelativeToCurrentWorkingDirectory() && user_exe_path) { // Ignore paths that start with "./" and "../" if (!((user_exe_path[0] == '.' && user_exe_path[1] == '/') || @@ -355,8 +434,8 @@ TargetList::CreateTarget (Debugger &debugger, if (platform_sp) { FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); - error = platform_sp->ResolveExecutable (file, - arch, + ModuleSpec module_spec(file, arch); + error = platform_sp->ResolveExecutable (module_spec, exe_module_sp, executable_search_paths.GetSize() ? &executable_search_paths : NULL); } @@ -378,7 +457,7 @@ TargetList::CreateTarget (Debugger &debugger, } return error; } - target_sp.reset(new Target(debugger, arch, platform_sp)); + target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target)); target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); if (user_exe_path_is_bundle) exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path, sizeof(resolved_bundle_exe_path)); @@ -388,7 +467,7 @@ TargetList::CreateTarget (Debugger &debugger, { // No file was specified, just create an empty target with any arch // if a valid arch was specified - target_sp.reset(new Target(debugger, arch, platform_sp)); + target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target)); } if (target_sp) @@ -415,11 +494,20 @@ TargetList::CreateTarget (Debugger &debugger, file_dir.GetDirectory() = file.GetDirectory(); target_sp->GetExecutableSearchPaths ().Append (file_dir); } - Mutex::Locker locker(m_target_list_mutex); - m_selected_target_idx = m_target_list.size(); - m_target_list.push_back(target_sp); - - + + // Don't put the dummy target in the target list, it's held separately. + if (!is_dummy_target) + { + Mutex::Locker locker(m_target_list_mutex); + m_selected_target_idx = m_target_list.size(); + m_target_list.push_back(target_sp); + // Now prime this from the dummy target: + target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget()); + } + else + { + m_dummy_target_sp = target_sp; + } } return error; diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp index a445517da6a8..b532d8d71c8f 100644 --- a/source/Target/Thread.cpp +++ b/source/Target/Thread.cpp @@ -32,6 +32,7 @@ #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanCallFunction.h" #include "lldb/Target/ThreadPlanBase.h" +#include "lldb/Target/ThreadPlanPython.h" #include "lldb/Target/ThreadPlanStepInstruction.h" #include "lldb/Target/ThreadPlanStepOut.h" #include "lldb/Target/ThreadPlanStepOverBreakpoint.h" @@ -43,7 +44,7 @@ #include "lldb/Target/ThreadSpec.h" #include "lldb/Target/Unwind.h" #include "Plugins/Process/Utility/UnwindLLDB.h" -#include "UnwindMacOSXFrameBackchain.h" +#include "Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h" using namespace lldb; @@ -278,6 +279,7 @@ Thread::Thread (Process &process, lldb::tid_t tid, bool use_invalid_index_id) : m_process_wp (process.shared_from_this()), m_stop_info_sp (), m_stop_info_stop_id (0), + m_stop_info_override_stop_id (0), m_index_id (use_invalid_index_id ? LLDB_INVALID_INDEX32 : process.GetNextThreadIndexID(tid)), m_reg_context_sp (), m_state (eStateUnloaded), @@ -465,6 +467,24 @@ Thread::GetPrivateStopInfo () SetStopInfo (StopInfoSP()); } } + + // The stop info can be manually set by calling Thread::SetStopInfo() + // prior to this function ever getting called, so we can't rely on + // "m_stop_info_stop_id != process_stop_id" as the condition for + // the if statement below, we must also check the stop info to see + // if we need to override it. See the header documentation in + // Process::GetStopInfoOverrideCallback() for more information on + // the stop info override callback. + if (m_stop_info_override_stop_id != process_stop_id) + { + m_stop_info_override_stop_id = process_stop_id; + if (m_stop_info_sp) + { + ArchSpec::StopInfoOverrideCallbackType callback = GetProcess()->GetStopInfoOverrideCallback(); + if (callback) + callback(*this); + } + } } return m_stop_info_sp; } @@ -642,7 +662,8 @@ Thread::SetupForResume () lldb::RegisterContextSP reg_ctx_sp (GetRegisterContext()); if (reg_ctx_sp) { - BreakpointSiteSP bp_site_sp = GetProcess()->GetBreakpointSiteList().FindByAddress(reg_ctx_sp->GetPC()); + const addr_t thread_pc = reg_ctx_sp->GetPC(); + BreakpointSiteSP bp_site_sp = GetProcess()->GetBreakpointSiteList().FindByAddress(thread_pc); if (bp_site_sp) { // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the target may not require anything @@ -650,19 +671,30 @@ Thread::SetupForResume () ThreadPlan *cur_plan = GetCurrentPlan(); - if (cur_plan->GetKind() != ThreadPlan::eKindStepOverBreakpoint) + bool push_step_over_bp_plan = false; + if (cur_plan->GetKind() == ThreadPlan::eKindStepOverBreakpoint) { - ThreadPlanStepOverBreakpoint *step_bp_plan = new ThreadPlanStepOverBreakpoint (*this); - if (step_bp_plan) + ThreadPlanStepOverBreakpoint *bp_plan = (ThreadPlanStepOverBreakpoint *)cur_plan; + if (bp_plan->GetBreakpointLoadAddress() != thread_pc) + push_step_over_bp_plan = true; + } + else + push_step_over_bp_plan = true; + + if (push_step_over_bp_plan) + { + ThreadPlanSP step_bp_plan_sp (new ThreadPlanStepOverBreakpoint (*this)); + if (step_bp_plan_sp) { - ThreadPlanSP step_bp_plan_sp; - step_bp_plan->SetPrivate (true); + ; + step_bp_plan_sp->SetPrivate (true); if (GetCurrentPlan()->RunState() != eStateStepping) { + ThreadPlanStepOverBreakpoint *step_bp_plan + = static_cast(step_bp_plan_sp.get()); step_bp_plan->SetAutoContinue(true); } - step_bp_plan_sp.reset (step_bp_plan); QueueThreadPlan (step_bp_plan_sp, false); } } @@ -941,30 +973,30 @@ Thread::ShouldStop (Event* event_ptr) if (over_ride_stop) should_stop = false; - // One other potential problem is that we set up a master plan, then stop in before it is complete - for instance - // by hitting a breakpoint during a step-over - then do some step/finish/etc operations that wind up - // past the end point condition of the initial plan. We don't want to strand the original plan on the stack, - // This code clears stale plans off the stack. + } + + // One other potential problem is that we set up a master plan, then stop in before it is complete - for instance + // by hitting a breakpoint during a step-over - then do some step/finish/etc operations that wind up + // past the end point condition of the initial plan. We don't want to strand the original plan on the stack, + // This code clears stale plans off the stack. - if (should_stop) + if (should_stop) + { + ThreadPlan *plan_ptr = GetCurrentPlan(); + while (!PlanIsBasePlan(plan_ptr)) { - ThreadPlan *plan_ptr = GetCurrentPlan(); - while (!PlanIsBasePlan(plan_ptr)) - { - bool stale = plan_ptr->IsPlanStale (); - ThreadPlan *examined_plan = plan_ptr; - plan_ptr = GetPreviousPlan (examined_plan); + bool stale = plan_ptr->IsPlanStale (); + ThreadPlan *examined_plan = plan_ptr; + plan_ptr = GetPreviousPlan (examined_plan); - if (stale) - { - if (log) - log->Printf("Plan %s being discarded in cleanup, it says it is already done.", - examined_plan->GetName()); - DiscardThreadPlansUpToPlan(examined_plan); - } + if (stale) + { + if (log) + log->Printf("Plan %s being discarded in cleanup, it says it is already done.", + examined_plan->GetName()); + DiscardThreadPlansUpToPlan(examined_plan); } } - } if (log) @@ -1290,6 +1322,36 @@ Thread::SetTracer (lldb::ThreadPlanTracerSP &tracer_sp) m_plan_stack[i]->SetThreadPlanTracer(tracer_sp); } +bool +Thread::DiscardUserThreadPlansUpToIndex (uint32_t thread_index) +{ + // Count the user thread plans from the back end to get the number of the one we want + // to discard: + + uint32_t idx = 0; + ThreadPlan *up_to_plan_ptr = nullptr; + + for (ThreadPlanSP plan_sp : m_plan_stack) + { + if (plan_sp->GetPrivate()) + continue; + if (idx == thread_index) + { + up_to_plan_ptr = plan_sp.get(); + break; + } + else + idx++; + } + + if (up_to_plan_ptr == nullptr) + return false; + + DiscardThreadPlansUpToPlan(up_to_plan_ptr); + return true; +} + + void Thread::DiscardThreadPlansUpToPlan (lldb::ThreadPlanSP &up_to_plan_sp) { @@ -1483,18 +1545,16 @@ Thread::QueueThreadPlanForStepInRange LazyBool step_out_avoids_code_without_debug_info ) { - ThreadPlanSP thread_plan_sp; - ThreadPlanStepInRange *plan = new ThreadPlanStepInRange (*this, + 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); + step_out_avoids_code_without_debug_info)); + ThreadPlanStepInRange *plan = static_cast(thread_plan_sp.get()); if (step_in_target) plan->SetStepInTarget(step_in_target); - - thread_plan_sp.reset (plan); QueueThreadPlan (thread_plan_sp, abort_other_plans); return thread_plan_sp; @@ -1546,17 +1606,18 @@ Thread::QueueThreadPlanForStepOutNoShouldStop uint32_t frame_idx ) { - ThreadPlanStepOut *new_plan = new ThreadPlanStepOut (*this, + ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut (*this, addr_context, first_insn, stop_other_threads, stop_vote, run_vote, frame_idx, - eLazyBoolNo); + eLazyBoolNo)); + + ThreadPlanStepOut *new_plan = static_cast(thread_plan_sp.get()); new_plan->ClearShouldStopHereCallbacks(); - ThreadPlanSP thread_plan_sp(new_plan); - + if (thread_plan_sp->ValidatePlan(NULL)) { QueueThreadPlan (thread_plan_sp, abort_other_plans); @@ -1602,61 +1663,105 @@ Thread::QueueThreadPlanForStepUntil (bool abort_other_plans, } +lldb::ThreadPlanSP +Thread::QueueThreadPlanForStepScripted (bool abort_other_plans, + const char *class_name, + bool stop_other_threads) +{ + ThreadPlanSP thread_plan_sp (new ThreadPlanPython (*this, class_name)); + QueueThreadPlan (thread_plan_sp, abort_other_plans); + // This seems a little funny, but I don't want to have to split up the constructor and the + // DidPush in the scripted plan, that seems annoying. + // That means the constructor has to be in DidPush. + // So I have to validate the plan AFTER pushing it, and then take it off again... + if (!thread_plan_sp->ValidatePlan(nullptr)) + { + DiscardThreadPlansUpToPlan(thread_plan_sp); + return ThreadPlanSP(); + } + else + return thread_plan_sp; + +} + uint32_t Thread::GetIndexID () const { return m_index_id; } -void -Thread::DumpThreadPlans (lldb_private::Stream *s) const +static void +PrintPlanElement (Stream *s, const ThreadPlanSP &plan, lldb::DescriptionLevel desc_level, int32_t elem_idx) { - uint32_t stack_size = m_plan_stack.size(); - int i; - s->Indent(); - s->Printf ("Plan Stack for thread #%u: tid = 0x%4.4" PRIx64 ", stack_size = %d\n", GetIndexID(), GetID(), stack_size); - for (i = stack_size - 1; i >= 0; i--) - { s->IndentMore(); s->Indent(); - s->Printf ("Element %d: ", i); - m_plan_stack[i]->GetDescription (s, eDescriptionLevelFull); + s->Printf ("Element %d: ", elem_idx); + plan->GetDescription (s, desc_level); s->EOL(); s->IndentLess(); +} + +static void +PrintPlanStack (Stream *s, const std::vector &plan_stack, lldb::DescriptionLevel desc_level, bool include_internal) +{ + int32_t print_idx = 0; + for (ThreadPlanSP plan_sp : plan_stack) + { + if (include_internal || !plan_sp->GetPrivate()) + { + PrintPlanElement (s, plan_sp, desc_level, print_idx++); + } } +} - stack_size = m_completed_plan_stack.size(); - if (stack_size > 0) +void +Thread::DumpThreadPlans (Stream *s, + lldb::DescriptionLevel desc_level, + bool include_internal, + bool ignore_boring_threads) const +{ + uint32_t stack_size; + + if (ignore_boring_threads) { - s->Indent(); - s->Printf ("Completed Plan Stack: %d elements.\n", stack_size); - for (i = stack_size - 1; i >= 0; i--) + uint32_t stack_size = m_plan_stack.size(); + uint32_t completed_stack_size = m_completed_plan_stack.size(); + uint32_t discarded_stack_size = m_discarded_plan_stack.size(); + if (stack_size == 1 && completed_stack_size == 0 && discarded_stack_size == 0) { + s->Printf ("thread #%u: tid = 0x%4.4" PRIx64 "\n", GetIndexID(), GetID()); s->IndentMore(); s->Indent(); - s->Printf ("Element %d: ", i); - m_completed_plan_stack[i]->GetDescription (s, eDescriptionLevelFull); - s->EOL(); + s->Printf("No active thread plans\n"); s->IndentLess(); + return; } } + s->Indent(); + s->Printf ("thread #%u: tid = 0x%4.4" PRIx64 ":\n", GetIndexID(), GetID()); + s->IndentMore(); + s->Indent(); + s->Printf ("Active plan stack:\n"); + PrintPlanStack (s, m_plan_stack, desc_level, include_internal); + + stack_size = m_completed_plan_stack.size(); + if (stack_size > 0) + { + s->Indent(); + s->Printf ("Completed Plan Stack:\n"); + PrintPlanStack (s, m_completed_plan_stack, desc_level, include_internal); + } + stack_size = m_discarded_plan_stack.size(); if (stack_size > 0) { s->Indent(); - s->Printf ("Discarded Plan Stack: %d elements.\n", stack_size); - for (i = stack_size - 1; i >= 0; i--) - { - s->IndentMore(); - s->Indent(); - s->Printf ("Element %d: ", i); - m_discarded_plan_stack[i]->GetDescription (s, eDescriptionLevelFull); - s->EOL(); - s->IndentLess(); - } + s->Printf ("Discarded Plan Stack:\n"); + PrintPlanStack (s, m_discarded_plan_stack, desc_level, include_internal); } + s->IndentLess(); } TargetSP @@ -1785,7 +1890,7 @@ Thread::ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return // FIXME: ValueObject::Cast doesn't currently work correctly, at least not for scalars. // Turn that back on when that works. - if (0 && sc.function != NULL) + if (/* DISABLES CODE */ (0) && sc.function != NULL) { Type *function_type = sc.function->GetType(); if (function_type) @@ -2011,6 +2116,7 @@ Thread::StopReasonAsCString (lldb::StopReason reason) case eStopReasonExec: return "exec"; case eStopReasonPlanComplete: return "plan complete"; case eStopReasonThreadExiting: return "thread exiting"; + case eStopReasonInstrumentation: return "instrumentation break"; } @@ -2090,17 +2196,28 @@ Thread::GetStatus (Stream &strm, uint32_t start_frame, uint32_t num_frames, uint } bool -Thread::GetDescription (Stream &strm, lldb::DescriptionLevel level, bool print_json) +Thread::GetDescription (Stream &strm, lldb::DescriptionLevel level, bool print_json_thread, bool print_json_stopinfo) { DumpUsingSettingsFormat (strm, 0); strm.Printf("\n"); StructuredData::ObjectSP thread_info = GetExtendedInfo(); - - if (thread_info && print_json) + StructuredData::ObjectSP stop_info = m_stop_info_sp->GetExtendedInfo(); + + if (print_json_thread || print_json_stopinfo) { - thread_info->Dump (strm); - strm.Printf("\n"); + if (thread_info && print_json_thread) + { + thread_info->Dump (strm); + strm.Printf("\n"); + } + + if (stop_info && print_json_stopinfo) + { + stop_info->Dump (strm); + strm.Printf("\n"); + } + return true; } @@ -2194,6 +2311,8 @@ Thread::GetUnwinder () case llvm::Triple::aarch64: case llvm::Triple::thumb: case llvm::Triple::mips64: + case llvm::Triple::ppc: + case llvm::Triple::ppc64: case llvm::Triple::hexagon: m_unwinder_ap.reset (new UnwindLLDB (*this)); break; diff --git a/source/Target/ThreadCollection.cpp b/source/Target/ThreadCollection.cpp new file mode 100644 index 000000000000..dc1e38e02420 --- /dev/null +++ b/source/Target/ThreadCollection.cpp @@ -0,0 +1,62 @@ +//===-- ThreadCollection.cpp ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include + +#include + +#include "lldb/Target/ThreadCollection.h" + +using namespace lldb; +using namespace lldb_private; + +ThreadCollection::ThreadCollection() : + m_threads(), + m_mutex() +{ +} + +ThreadCollection::ThreadCollection(collection threads) : + m_threads(threads), + m_mutex() +{ +} + +void +ThreadCollection::AddThread (const ThreadSP &thread_sp) +{ + Mutex::Locker locker(GetMutex()); + m_threads.push_back (thread_sp); +} + +void +ThreadCollection::InsertThread (const lldb::ThreadSP &thread_sp, uint32_t idx) +{ + Mutex::Locker locker(GetMutex()); + if (idx < m_threads.size()) + m_threads.insert(m_threads.begin() + idx, thread_sp); + else + m_threads.push_back (thread_sp); +} + +uint32_t +ThreadCollection::GetSize () +{ + Mutex::Locker locker(GetMutex()); + return m_threads.size(); +} + +ThreadSP +ThreadCollection::GetThreadAtIndex (uint32_t idx) +{ + Mutex::Locker locker(GetMutex()); + ThreadSP thread_sp; + if (idx < m_threads.size()) + thread_sp = m_threads[idx]; + return thread_sp; +} diff --git a/source/Target/ThreadList.cpp b/source/Target/ThreadList.cpp index 7fb16fdac5c0..db4407b4b579 100644 --- a/source/Target/ThreadList.cpp +++ b/source/Target/ThreadList.cpp @@ -22,17 +22,17 @@ using namespace lldb; using namespace lldb_private; ThreadList::ThreadList (Process *process) : + ThreadCollection(), m_process (process), m_stop_id (0), - m_threads(), m_selected_tid (LLDB_INVALID_THREAD_ID) { } ThreadList::ThreadList (const ThreadList &rhs) : + ThreadCollection(), m_process (rhs.m_process), m_stop_id (rhs.m_stop_id), - m_threads (), m_selected_tid () { // Use the assignment operator since it uses the mutex @@ -77,25 +77,6 @@ ThreadList::SetStopID (uint32_t stop_id) m_stop_id = stop_id; } - -void -ThreadList::AddThread (const ThreadSP &thread_sp) -{ - Mutex::Locker locker(GetMutex()); - m_threads.push_back(thread_sp); -} - -void -ThreadList::InsertThread (const lldb::ThreadSP &thread_sp, uint32_t idx) -{ - Mutex::Locker locker(GetMutex()); - if (idx < m_threads.size()) - m_threads.insert(m_threads.begin() + idx, thread_sp); - else - m_threads.push_back (thread_sp); -} - - uint32_t ThreadList::GetSize (bool can_update) { diff --git a/source/Target/ThreadPlanPython.cpp b/source/Target/ThreadPlanPython.cpp new file mode 100644 index 000000000000..e196d81c897a --- /dev/null +++ b/source/Target/ThreadPlanPython.cpp @@ -0,0 +1,192 @@ +//===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/lldb-python.h" + +#include "lldb/Target/ThreadPlan.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/State.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Interpreter/ScriptInterpreterPython.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanPython.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; + +//---------------------------------------------------------------------- +// ThreadPlanPython +//---------------------------------------------------------------------- + +ThreadPlanPython::ThreadPlanPython (Thread &thread, const char *class_name) : + ThreadPlan (ThreadPlan::eKindPython, + "Python based Thread Plan", + thread, + eVoteNoOpinion, + eVoteNoOpinion), + m_class_name (class_name) +{ + SetIsMasterPlan (true); + SetOkayToDiscard (true); + SetPrivate (false); +} + +ThreadPlanPython::~ThreadPlanPython () +{ + // FIXME, do I need to decrement the ref count on this implementation object to make it go away? +} + +bool +ThreadPlanPython::ValidatePlan (Stream *error) +{ + // I have to postpone setting up the implementation till after the constructor because I need to call + // shared_from_this, which you can't do in the constructor. So I'll do it here. + if (m_implementation_sp) + return true; + else + return false; +} + +void +ThreadPlanPython::DidPush() +{ + // We set up the script side in DidPush, so that it can push other plans in the constructor, + // and doesn't have to care about the details of DidPush. + + if (!m_class_name.empty()) + { + ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + if (script_interp) + { + m_implementation_sp = script_interp->CreateScriptedThreadPlan (m_class_name.c_str(), this->shared_from_this()); + } + } +} + +bool +ThreadPlanPython::ShouldStop (Event *event_ptr) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); + if (log) + log->Printf ("%s called on Python Thread Plan: %s )", + __PRETTY_FUNCTION__, m_class_name.c_str()); + + bool should_stop = true; + if (m_implementation_sp) + { + ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + if (script_interp) + { + bool script_error; + should_stop = script_interp->ScriptedThreadPlanShouldStop (m_implementation_sp, event_ptr, script_error); + if (script_error) + SetPlanComplete(false); + } + } + return should_stop; +} + +bool +ThreadPlanPython::DoPlanExplainsStop (Event *event_ptr) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); + if (log) + log->Printf ("%s called on Python Thread Plan: %s )", + __PRETTY_FUNCTION__, m_class_name.c_str()); + + bool explains_stop = true; + if (m_implementation_sp) + { + ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + if (script_interp) + { + bool script_error; + explains_stop = script_interp->ScriptedThreadPlanExplainsStop (m_implementation_sp, event_ptr, script_error); + if (script_error) + SetPlanComplete(false); + } + } + return explains_stop; +} + +bool +ThreadPlanPython::MischiefManaged () +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); + if (log) + log->Printf ("%s called on Python Thread Plan: %s )", + __PRETTY_FUNCTION__, m_class_name.c_str()); + bool mischief_managed = true; + if (m_implementation_sp) + { + // I don't really need mischief_managed, since it's simpler to just call SetPlanComplete in should_stop. + mischief_managed = IsPlanComplete(); + if (mischief_managed) + m_implementation_sp.reset(); + } + return mischief_managed; +} + +lldb::StateType +ThreadPlanPython::GetPlanRunState () +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); + if (log) + log->Printf ("%s called on Python Thread Plan: %s )", + __PRETTY_FUNCTION__, + m_class_name.c_str()); + lldb::StateType run_state = eStateRunning; + if (m_implementation_sp) + { + ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + if (script_interp) + { + bool script_error; + run_state = script_interp->ScriptedThreadPlanGetRunState (m_implementation_sp, script_error); + } + } + return run_state; +} + +// The ones below are not currently exported to Python. + +bool +ThreadPlanPython::StopOthers () +{ + // For now Python plans run all threads, but we should add some controls for this. + return false; +} + +void +ThreadPlanPython::GetDescription (Stream *s, + lldb::DescriptionLevel level) +{ + s->Printf ("Python thread plan implemented by class %s.", m_class_name.c_str()); +} + +bool +ThreadPlanPython::WillStop () +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); + if (log) + log->Printf ("%s called on Python Thread Plan: %s )", + __PRETTY_FUNCTION__, m_class_name.c_str()); + return true; +} diff --git a/source/Target/ThreadPlanStepInRange.cpp b/source/Target/ThreadPlanStepInRange.cpp index 3e9abef65573..e5f057c183fb 100644 --- a/source/Target/ThreadPlanStepInRange.cpp +++ b/source/Target/ThreadPlanStepInRange.cpp @@ -105,7 +105,6 @@ ThreadPlanStepInRange::SetupAvoidNoDebug(LazyBool step_in_avoids_code_without_de else GetFlags().Clear (ThreadPlanShouldStopHere::eStepInAvoidNoDebug); - avoid_nodebug = true; switch (step_out_avoids_code_without_debug_info) { case eLazyBoolYes: @@ -128,17 +127,31 @@ void ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level) { if (level == lldb::eDescriptionLevelBrief) + { s->Printf("step in"); - else + return; + } + + s->Printf ("Stepping in"); + bool printed_line_info = false; + if (m_addr_context.line_entry.IsValid()) + { + s->Printf (" through line "); + m_addr_context.line_entry.DumpStopContext (s, false); + printed_line_info = true; + } + + const char *step_into_target = m_step_into_target.AsCString(); + if (step_into_target && step_into_target[0] != '\0') + s->Printf (" targeting %s", m_step_into_target.AsCString()); + + if (!printed_line_info || level == eDescriptionLevelVerbose) { - s->Printf ("Stepping through range (stepping into functions): "); + s->Printf (" using ranges:"); DumpRanges(s); - const char *step_into_target = m_step_into_target.AsCString(); - if (step_into_target && step_into_target[0] != '\0') - s->Printf (" targeting %s.", m_step_into_target.AsCString()); - else - s->PutChar('.'); } + + s->PutChar('.'); } bool @@ -303,6 +316,7 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr) else { m_no_more_plans = false; + m_sub_plan_sp->SetPrivate(true); return false; } } diff --git a/source/Target/ThreadPlanStepInstruction.cpp b/source/Target/ThreadPlanStepInstruction.cpp index fabf63b1e9d6..0f6d7b78a9ce 100644 --- a/source/Target/ThreadPlanStepInstruction.cpp +++ b/source/Target/ThreadPlanStepInstruction.cpp @@ -150,7 +150,16 @@ ThreadPlanStepInstruction::ShouldStop (Event *event_ptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - StackID cur_frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); + StackFrameSP cur_frame_sp = m_thread.GetStackFrameAtIndex(0); + if (!cur_frame_sp) + { + if (log) + log->Printf ("ThreadPlanStepInstruction couldn't get the 0th frame, stopping."); + SetPlanComplete(); + return true; + } + + StackID cur_frame_zero_id = cur_frame_sp->GetStackID(); if (cur_frame_zero_id == m_stack_id || m_stack_id < cur_frame_zero_id) { @@ -180,6 +189,24 @@ ThreadPlanStepInstruction::ShouldStop (Event *event_ptr) { if (return_frame->GetStackID() != m_parent_frame_id || m_start_has_symbol) { + // next-instruction shouldn't step out of inlined functions. But we may have stepped into a + // real function that starts with an inlined function, and we do want to step out of that... + + if (cur_frame_sp->IsInlined()) + { + StackFrameSP parent_frame_sp = m_thread.GetFrameWithStackID(m_stack_id); + + if(parent_frame_sp && parent_frame_sp->GetConcreteFrameIndex() == cur_frame_sp->GetConcreteFrameIndex()) + { + SetPlanComplete(); + if (log) + { + log->Printf("Frame we stepped into is inlined into the frame we were stepping from, stopping."); + } + return true; + } + } + if (log) { StreamString s; diff --git a/source/Target/ThreadPlanStepOut.cpp b/source/Target/ThreadPlanStepOut.cpp index b62f557319a8..0ded99b3091d 100644 --- a/source/Target/ThreadPlanStepOut.cpp +++ b/source/Target/ThreadPlanStepOut.cpp @@ -54,7 +54,6 @@ ThreadPlanStepOut::ThreadPlanStepOut m_return_addr (LLDB_INVALID_ADDRESS), m_stop_others (stop_others), m_immediate_step_from_function(NULL) - { SetFlagsToDefault(); SetupAvoidNoDebug(step_out_avoids_code_without_debug_info); @@ -90,6 +89,7 @@ ThreadPlanStepOut::ThreadPlanStepOut frame_idx - 1, eLazyBoolNo)); static_cast(m_step_out_to_inline_plan_sp.get())->SetShouldStopHereCallbacks(nullptr, nullptr); + m_step_out_to_inline_plan_sp->SetPrivate(true); } else { @@ -177,10 +177,34 @@ ThreadPlanStepOut::GetDescription (Stream *s, lldb::DescriptionLevel level) else if (m_step_through_inline_plan_sp) s->Printf ("Stepping out by stepping through inlined function."); else - s->Printf ("Stepping out from address 0x%" PRIx64 " to return address 0x%" PRIx64 " using breakpoint site %d", - (uint64_t)m_step_from_insn, - (uint64_t)m_return_addr, - m_return_bp_id); + { + s->Printf ("Stepping out from "); + Address tmp_address; + if (tmp_address.SetLoadAddress (m_step_from_insn, &GetTarget())) + { + tmp_address.Dump(s, &GetThread(), Address::DumpStyleResolvedDescription, Address::DumpStyleLoadAddress); + } + else + { + s->Printf ("address 0x%" PRIx64 "", (uint64_t)m_step_from_insn); + } + + // FIXME: find some useful way to present the m_return_id, since there may be multiple copies of the + // same function on the stack. + + s->Printf ("returning to frame at "); + if (tmp_address.SetLoadAddress (m_return_addr, &GetTarget())) + { + tmp_address.Dump(s, &GetThread(), Address::DumpStyleResolvedDescription, Address::DumpStyleLoadAddress); + } + else + { + s->Printf ("address 0x%" PRIx64 "", (uint64_t)m_return_addr); + } + + if (level == eDescriptionLevelVerbose) + s->Printf(" using breakpoint site %d", m_return_bp_id); + } } } @@ -474,11 +498,16 @@ ThreadPlanStepOut::QueueInlinedStepPlan (bool queue_now) inlined_sc.target_sp = GetTarget().shared_from_this(); RunMode run_mode = m_stop_others ? lldb::eOnlyThisThread : lldb::eAllThreads; const LazyBool avoid_no_debug = eLazyBoolNo; - ThreadPlanStepOverRange *step_through_inline_plan_ptr = new ThreadPlanStepOverRange(m_thread, - inline_range, - inlined_sc, - run_mode, - avoid_no_debug); + + m_step_through_inline_plan_sp.reset (new ThreadPlanStepOverRange(m_thread, + inline_range, + inlined_sc, + run_mode, + avoid_no_debug)); + ThreadPlanStepOverRange *step_through_inline_plan_ptr + = static_cast(m_step_through_inline_plan_sp.get()); + m_step_through_inline_plan_sp->SetPrivate(true); + step_through_inline_plan_ptr->SetOkayToDiscard(true); StreamString errors; if (!step_through_inline_plan_ptr->ValidatePlan(&errors)) @@ -493,7 +522,7 @@ ThreadPlanStepOut::QueueInlinedStepPlan (bool queue_now) if (inlined_block->GetRangeAtIndex (i, inline_range)) step_through_inline_plan_ptr->AddRange (inline_range); } - m_step_through_inline_plan_sp.reset (step_through_inline_plan_ptr); + if (queue_now) m_thread.QueueThreadPlan (m_step_through_inline_plan_sp, false); return true; diff --git a/source/Target/ThreadPlanStepOverBreakpoint.cpp b/source/Target/ThreadPlanStepOverBreakpoint.cpp index dc011e545402..6f285e25fd0b 100644 --- a/source/Target/ThreadPlanStepOverBreakpoint.cpp +++ b/source/Target/ThreadPlanStepOverBreakpoint.cpp @@ -64,11 +64,33 @@ 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(); - if (reason == eStopReasonTrace || reason == eStopReasonNone) + + switch (reason) + { + case eStopReasonTrace: + case eStopReasonNone: return true; - else + case eStopReasonBreakpoint: + // 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 hit. So our trace + // step COULD appear as a breakpoint hit if the next instruction also contained a breakpoint. We don't want + // to handle that, since we really don't know what to do with breakpoint hits. But make sure we don't set + // ourselves to auto-continue or we'll wrench control away from the plans that can deal with this. + SetAutoContinue(false); + return false; + default: return false; + } } return false; } @@ -76,7 +98,7 @@ ThreadPlanStepOverBreakpoint::DoPlanExplainsStop (Event *event_ptr) bool ThreadPlanStepOverBreakpoint::ShouldStop (Event *event_ptr) { - return false; + return !ShouldAutoContinue(event_ptr); } bool @@ -163,3 +185,10 @@ ThreadPlanStepOverBreakpoint::ShouldAutoContinue (Event *event_ptr) { return m_auto_continue; } + +bool +ThreadPlanStepOverBreakpoint::IsPlanStale() +{ + return m_thread.GetRegisterContext()->GetPC() != m_breakpoint_addr; +} + diff --git a/source/Target/ThreadPlanStepOverRange.cpp b/source/Target/ThreadPlanStepOverRange.cpp index a4f3743346e2..a6d65e4d8116 100644 --- a/source/Target/ThreadPlanStepOverRange.cpp +++ b/source/Target/ThreadPlanStepOverRange.cpp @@ -62,12 +62,26 @@ void ThreadPlanStepOverRange::GetDescription (Stream *s, lldb::DescriptionLevel level) { if (level == lldb::eDescriptionLevelBrief) + { s->Printf("step over"); - else + return; + } + s->Printf ("Stepping over"); + bool printed_line_info = false; + if (m_addr_context.line_entry.IsValid()) + { + s->Printf (" line "); + m_addr_context.line_entry.DumpStopContext (s, false); + printed_line_info = true; + } + + if (!printed_line_info || level == eDescriptionLevelVerbose) { - s->Printf ("stepping through range (stepping over functions): "); - DumpRanges(s); + s->Printf (" using ranges: "); + DumpRanges(s); } + + s->PutChar('.'); } void @@ -317,11 +331,15 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr) { new_plan_sp = CheckShouldStopHereAndQueueStepOut (frame_order); } - + if (!new_plan_sp) m_no_more_plans = true; else + { + // Any new plan will be an implementation plan, so mark it private: + new_plan_sp->SetPrivate(true); m_no_more_plans = false; + } if (!new_plan_sp) { diff --git a/source/Target/ThreadPlanStepRange.cpp b/source/Target/ThreadPlanStepRange.cpp index 82ca59fbca39..adc515cebc08 100644 --- a/source/Target/ThreadPlanStepRange.cpp +++ b/source/Target/ThreadPlanStepRange.cpp @@ -44,7 +44,8 @@ ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind, Thread &thread, const AddressRange &range, const SymbolContext &addr_context, - lldb::RunMode stop_others) : + lldb::RunMode stop_others, + bool given_ranges_only) : ThreadPlan (kind, name, thread, eVoteNoOpinion, eVoteNoOpinion), m_addr_context (addr_context), m_address_ranges (), @@ -53,7 +54,8 @@ ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind, m_parent_stack_id(), m_no_more_plans (false), m_first_run_event (true), - m_use_fast_step(false) + m_use_fast_step(false), + m_given_ranges_only (given_ranges_only) { m_use_fast_step = GetTarget().GetUseFastStepping(); AddRange(range); @@ -149,7 +151,7 @@ ThreadPlanStepRange::InRange () break; } - if (!ret_value) + if (!ret_value && !m_given_ranges_only) { // See if we've just stepped to another part of the same line number... StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get(); diff --git a/source/Target/ThreadPlanStepThrough.cpp b/source/Target/ThreadPlanStepThrough.cpp index 18da6cdbd59c..5b50a41a6398 100644 --- a/source/Target/ThreadPlanStepThrough.cpp +++ b/source/Target/ThreadPlanStepThrough.cpp @@ -87,7 +87,10 @@ ThreadPlanStepThrough::DidPush () void ThreadPlanStepThrough::LookForPlanToStepThroughFromCurrentPC() { - m_sub_plan_sp = m_thread.GetProcess()->GetDynamicLoader()->GetStepThroughTrampolinePlan (m_thread, m_stop_others); + DynamicLoader *loader = m_thread.GetProcess()->GetDynamicLoader(); + if (loader) + m_sub_plan_sp = loader->GetStepThroughTrampolinePlan (m_thread, m_stop_others); + // If that didn't come up with anything, try the ObjC runtime plugin: if (!m_sub_plan_sp.get()) { diff --git a/source/Target/ThreadPlanTracer.cpp b/source/Target/ThreadPlanTracer.cpp index 5188df6d9193..d2b039d69f67 100644 --- a/source/Target/ThreadPlanTracer.cpp +++ b/source/Target/ThreadPlanTracer.cpp @@ -212,11 +212,15 @@ ThreadPlanAssemblyTracer::Log () const bool show_bytes = true; const bool show_address = true; Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get(); + const char *disassemble_format = "${addr-file-or-load}: "; instruction->Dump (stream, max_opcode_byte_size, show_address, show_bytes, - NULL); + NULL, + NULL, + NULL, + disassemble_format); } } } diff --git a/source/Utility/PseudoTerminal.cpp b/source/Utility/PseudoTerminal.cpp index c906ea273005..e90955d37d4c 100644 --- a/source/Utility/PseudoTerminal.cpp +++ b/source/Utility/PseudoTerminal.cpp @@ -31,6 +31,8 @@ char *ptsname(int fd) { return 0; } pid_t fork(void) { return 0; } pid_t setsid(void) { return 0; } +#elif defined(__ANDROID_NDK__) +#include "lldb/Host/android/Android.h" #endif using namespace lldb_utility; @@ -66,7 +68,11 @@ PseudoTerminal::CloseMasterFileDescriptor () { if (m_master_fd >= 0) { + // Don't call 'close' on m_master_fd for Windows as a dummy implementation of + // posix_openpt above always gives it a 0 value. +#ifndef _WIN32 ::close (m_master_fd); +#endif m_master_fd = invalid_fd; } } diff --git a/source/Utility/RegisterNumber.cpp b/source/Utility/RegisterNumber.cpp new file mode 100644 index 000000000000..8116cda10fe5 --- /dev/null +++ b/source/Utility/RegisterNumber.cpp @@ -0,0 +1,157 @@ +//===--------------------- RegisterNumber.cpp -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/RegisterNumber.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/RegisterContext.h" + +using namespace lldb_private; + + +RegisterNumber::RegisterNumber (lldb_private::Thread &thread, lldb::RegisterKind kind, uint32_t num) : + m_reg_ctx_sp (thread.GetRegisterContext()), + m_regnum (num), + m_kind (kind), + m_kind_regnum_map (), + m_name ("") +{ + if (m_reg_ctx_sp.get()) + { + const lldb_private::RegisterInfo *reginfo = m_reg_ctx_sp->GetRegisterInfoAtIndex (GetAsKind (lldb::eRegisterKindLLDB)); + if (reginfo && reginfo->name) + { + m_name = reginfo->name; + } + } +} + +RegisterNumber::RegisterNumber () : + m_reg_ctx_sp(), + m_regnum (LLDB_INVALID_REGNUM), + m_kind (lldb::kNumRegisterKinds), + m_kind_regnum_map (), + m_name (nullptr) +{ +} + +void +RegisterNumber::init (lldb_private::Thread &thread, lldb::RegisterKind kind, uint32_t num) +{ + m_reg_ctx_sp = thread.GetRegisterContext(); + m_regnum = num; + m_kind = kind; + if (m_reg_ctx_sp.get()) + { + const lldb_private::RegisterInfo *reginfo = m_reg_ctx_sp->GetRegisterInfoAtIndex (GetAsKind (lldb::eRegisterKindLLDB)); + if (reginfo && reginfo->name) + { + m_name = reginfo->name; + } + } +} + +const RegisterNumber & +RegisterNumber::operator = (const RegisterNumber &rhs) +{ + m_reg_ctx_sp = rhs.m_reg_ctx_sp; + m_regnum = rhs.m_regnum; + m_kind = rhs.m_kind; + for (auto it : rhs.m_kind_regnum_map) + m_kind_regnum_map[it.first] = it.second; + m_name = rhs.m_name; + return *this; +} + +bool +RegisterNumber::operator == (RegisterNumber &rhs) +{ + if (IsValid() != rhs.IsValid()) + return false; + + if (m_kind == rhs.m_kind) + { + if (m_regnum == rhs.m_regnum) + return true; + else + return false; + } + + uint32_t rhs_regnum = rhs.GetAsKind (m_kind); + if (rhs_regnum != LLDB_INVALID_REGNUM) + { + if (m_regnum == rhs_regnum) + return true; + else + return false; + } + uint32_t lhs_regnum = GetAsKind (rhs.m_kind); + { + if (lhs_regnum == rhs.m_regnum) + return true; + else + return false; + } + return false; +} + +bool +RegisterNumber::operator != (RegisterNumber &rhs) +{ + return !(*this == rhs); +} + +bool +RegisterNumber::IsValid () const +{ + return m_reg_ctx_sp.get() + && m_kind != lldb::kNumRegisterKinds + && m_regnum != LLDB_INVALID_REGNUM; +} + +uint32_t +RegisterNumber::GetAsKind (lldb::RegisterKind kind) +{ + if (m_regnum == LLDB_INVALID_REGNUM) + return LLDB_INVALID_REGNUM; + + if (kind == m_kind) + return m_regnum; + + Collection::iterator iter = m_kind_regnum_map.find (kind); + if (iter != m_kind_regnum_map.end()) + { + return iter->second; + } + uint32_t output_regnum = LLDB_INVALID_REGNUM; + if (m_reg_ctx_sp + && m_reg_ctx_sp->ConvertBetweenRegisterKinds (m_kind, m_regnum, kind, output_regnum) + && output_regnum != LLDB_INVALID_REGNUM) + { + m_kind_regnum_map[kind] = output_regnum; + } + return output_regnum; +} + +uint32_t +RegisterNumber::GetRegisterNumber () const +{ + return m_regnum; +} + +lldb::RegisterKind +RegisterNumber::GetRegisterKind () const +{ + return m_kind; +} + +const char * +RegisterNumber::GetName () +{ + return m_name; +} diff --git a/source/Utility/StringExtractor.cpp b/source/Utility/StringExtractor.cpp index 8747853213cb..a2cbe6cd4869 100644 --- a/source/Utility/StringExtractor.cpp +++ b/source/Utility/StringExtractor.cpp @@ -16,43 +16,6 @@ // Other libraries and framework includes // Project includes -static const uint8_t -g_hex_ascii_to_hex_integer[256] = { - - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 255, 255, 255, 255, 255, 255, - 255, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, -}; - static inline int xdigit_to_sint (char ch) { @@ -60,7 +23,9 @@ xdigit_to_sint (char ch) return 10 + ch - 'a'; if (ch >= 'A' && ch <= 'F') return 10 + ch - 'A'; - return ch - '0'; + if (ch >= '0' && ch <= '9') + return ch - '0'; + return -1; } //---------------------------------------------------------------------- @@ -128,6 +93,31 @@ StringExtractor::GetChar (char fail_value) return fail_value; } +//---------------------------------------------------------------------- +// If a pair of valid hex digits exist at the head of the +// StringExtractor they are decoded into an unsigned byte and returned +// by this function +// +// If there is not a pair of valid hex digits at the head of the +// StringExtractor, it is left unchanged and -1 is returned +//---------------------------------------------------------------------- +int +StringExtractor::DecodeHexU8() +{ + if (GetBytesLeft() < 2) + { + return -1; + } + const int hi_nibble = xdigit_to_sint(m_packet[m_index]); + const int lo_nibble = xdigit_to_sint(m_packet[m_index+1]); + if (hi_nibble == -1 || lo_nibble == -1) + { + return -1; + } + m_index += 2; + return (uint8_t)((hi_nibble << 4) + lo_nibble); +} + //---------------------------------------------------------------------- // Extract an unsigned character from two hex ASCII chars in the packet // string @@ -135,19 +125,14 @@ StringExtractor::GetChar (char fail_value) uint8_t StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail) { - if (GetBytesLeft() >= 2) + int byte = DecodeHexU8(); + if (byte == -1) { - const uint8_t hi_nibble = g_hex_ascii_to_hex_integer[static_cast(m_packet[m_index])]; - const uint8_t lo_nibble = g_hex_ascii_to_hex_integer[static_cast(m_packet[m_index+1])]; - if (hi_nibble < 16 && lo_nibble < 16) - { - m_index += 2; - return (hi_nibble << 4) + lo_nibble; - } + if (set_eof_on_fail || m_index >= m_packet.size()) + m_index = UINT64_MAX; + return fail_value; } - if (set_eof_on_fail || m_index >= m_packet.size()) - m_index = UINT64_MAX; - return fail_value; + return (uint8_t)byte; } uint32_t @@ -372,6 +357,28 @@ StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_ return bytes_extracted; } +//---------------------------------------------------------------------- +// Decodes all valid hex encoded bytes at the head of the +// StringExtractor, limited by dst_len. +// +// Returns the number of bytes successfully decoded +//---------------------------------------------------------------------- +size_t +StringExtractor::GetHexBytesAvail (void *dst_void, size_t dst_len) +{ + uint8_t *dst = (uint8_t*)dst_void; + size_t bytes_extracted = 0; + while (bytes_extracted < dst_len) + { + int decode = DecodeHexU8(); + if (decode == -1) + { + break; + } + dst[bytes_extracted++] = (uint8_t)decode; + } + return bytes_extracted; +} // Consume ASCII hex nibble character pairs until we have decoded byte_size // bytes of data. diff --git a/source/Utility/StringExtractor.h b/source/Utility/StringExtractor.h index 697499309ced..49dfe99bd358 100644 --- a/source/Utility/StringExtractor.h +++ b/source/Utility/StringExtractor.h @@ -92,9 +92,13 @@ public: return m_packet.size() - m_index; return 0; } + char GetChar (char fail_value = '\0'); + int + DecodeHexU8(); + uint8_t GetHexU8 (uint8_t fail_value = 0, bool set_eof_on_fail = true); @@ -122,6 +126,9 @@ public: size_t GetHexBytes (void *dst, size_t dst_len, uint8_t fail_fill_value); + size_t + GetHexBytesAvail (void *dst, size_t dst_len); + uint64_t GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value); diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp index 17717dbe6e20..161ac6a026f2 100644 --- a/source/Utility/StringExtractorGDBRemote.cpp +++ b/source/Utility/StringExtractorGDBRemote.cpp @@ -346,14 +346,15 @@ StringExtractorGDBRemote::GetError () size_t StringExtractorGDBRemote::GetEscapedBinaryData (std::string &str) { + // Just get the data bytes in the string as GDBRemoteCommunication::CheckForPacket() + // already removes any 0x7d escaped characters. If any 0x7d characters are left in + // the packet, then they are supposed to be there... str.clear(); - char ch; - while (GetBytesLeft()) + const size_t bytes_left = GetBytesLeft(); + if (bytes_left > 0) { - ch = GetChar(); - if (ch == 0x7d) - ch = (GetChar() ^ 0x20); - str.append(1,ch); + str.assign(m_packet, m_index, bytes_left); + m_index += bytes_left; } return str.size(); } diff --git a/source/Utility/StringLexer.cpp b/source/Utility/StringLexer.cpp index bde2fc6a4202..2f62d2cedb40 100644 --- a/source/Utility/StringLexer.cpp +++ b/source/Utility/StringLexer.cpp @@ -10,28 +10,24 @@ #include "lldb/Utility/StringLexer.h" #include +#include using namespace lldb_utility; StringLexer::StringLexer (std::string s) : -m_data(s), -m_position(0), -m_putback_data() + m_data(s), + m_position(0) { } StringLexer::StringLexer (const StringLexer& rhs) : -m_data(rhs.m_data), -m_position(rhs.m_position), -m_putback_data(rhs.m_putback_data) + m_data(rhs.m_data), + m_position(rhs.m_position) { } StringLexer::Character StringLexer::Peek () { - if (m_putback_data.empty()) - return m_data[m_position]; - else - return m_putback_data.front(); + return m_data[m_position]; } bool @@ -46,6 +42,42 @@ StringLexer::NextIf (Character c) return false; } +std::pair +StringLexer::NextIf (std::initializer_list cs) +{ + auto val = Peek(); + for (auto c : cs) + { + if (val == c) + { + Next(); + return {true,c}; + } + } + return {false,0}; +} + +bool +StringLexer::AdvanceIf (const std::string& token) +{ + auto pos = m_position; + bool matches = true; + for (auto c : token) + { + if (!NextIf(c)) + { + matches = false; + break; + } + } + if (!matches) + { + m_position = pos; + return false; + } + return true; +} + StringLexer::Character StringLexer::Next () { @@ -57,35 +89,32 @@ StringLexer::Next () bool StringLexer::HasAtLeast (Size s) { - auto in_m_data = m_data.size()-m_position; - auto in_putback = m_putback_data.size(); - return (in_m_data + in_putback >= s); + return (m_data.size() - m_position) >= s; } - void -StringLexer::PutBack (Character c) +StringLexer::PutBack (Size s) { - m_putback_data.push_back(c); + assert (m_position >= s); + m_position -= s; } bool StringLexer::HasAny (Character c) { - const auto begin(m_putback_data.begin()); - const auto end(m_putback_data.end()); - if (std::find(begin, end, c) != end) - return true; return m_data.find(c, m_position) != std::string::npos; } +std::string +StringLexer::GetUnlexed () +{ + return std::string(m_data, m_position); +} + void StringLexer::Consume() { - if (m_putback_data.empty()) - m_position++; - else - m_putback_data.pop_front(); + m_position++; } StringLexer& @@ -95,7 +124,6 @@ StringLexer::operator = (const StringLexer& rhs) { m_data = rhs.m_data; m_position = rhs.m_position; - m_putback_data = rhs.m_putback_data; } return *this; } diff --git a/source/Utility/UriParser.cpp b/source/Utility/UriParser.cpp new file mode 100644 index 000000000000..bf1e601485b4 --- /dev/null +++ b/source/Utility/UriParser.cpp @@ -0,0 +1,58 @@ +//===-- UriParser.cpp -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Utility/UriParser.h" + +// C Includes +#include + +// C++ Includes +// Other libraries and framework includes +// Project includes + +//---------------------------------------------------------------------- +// UriParser::Parse +//---------------------------------------------------------------------- +bool +UriParser::Parse(const char* uri, + std::string& scheme, + std::string& hostname, + int& port, + std::string& path + ) +{ + char scheme_buf[100] = {0}; + char hostname_buf[256] = {0}; + char port_buf[11] = {0}; // 10==strlen(2^32) + char path_buf[2049] = {'/', 0}; + + bool ok = false; + if (4==sscanf(uri, "%99[^:/]://%255[^/:]:%[^/]/%2047s", scheme_buf, hostname_buf, port_buf, path_buf+1)) { ok = true; } + else if (3==sscanf(uri, "%99[^:/]://%255[^/:]:%[^/]", scheme_buf, hostname_buf, port_buf)) { ok = true; } + else if (3==sscanf(uri, "%99[^:/]://%255[^/]/%2047s", scheme_buf, hostname_buf, path_buf+1)) { ok = true; } + else if (2==sscanf(uri, "%99[^:/]://%255[^/]", scheme_buf, hostname_buf)) { ok = true; } + + char* end = port_buf; + int port_tmp = strtoul(port_buf, &end, 10); + if (*end != 0) + { + // there are invalid characters in port_buf + return false; + } + + if (ok) + { + scheme.assign(scheme_buf); + hostname.assign(hostname_buf); + port = port_tmp; + path.assign(path_buf); + } + return ok; +} + diff --git a/source/Utility/UriParser.h b/source/Utility/UriParser.h new file mode 100644 index 000000000000..c46628d3bd68 --- /dev/null +++ b/source/Utility/UriParser.h @@ -0,0 +1,31 @@ +//===-- UriParser.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_UriParser_h_ +#define utility_UriParser_h_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes + +class UriParser +{ +public: + static bool Parse(const char* uri, + std::string& scheme, + std::string& hostname, + int& port, + std::string& path + ); +}; + +#endif // utility_UriParser_h_ diff --git a/source/lldb-log.cpp b/source/lldb-log.cpp index 4311c1ad084f..463de137f623 100644 --- a/source/lldb-log.cpp +++ b/source/lldb-log.cpp @@ -11,6 +11,7 @@ // C Includes // C++ Includes +#include // Other libraries and framework includes // Project includes #include "lldb/Interpreter/Args.h" @@ -27,7 +28,7 @@ using namespace lldb_private; // that will construct the static g_lob_sp the first time this function is // called. -static bool g_log_enabled = false; +static std::atomic g_log_enabled {false}; static Log * g_log = NULL; static Log * GetLog () diff --git a/source/lldb.cpp b/source/lldb.cpp index cd620b7945b9..2ac8296b4d04 100644 --- a/source/lldb.cpp +++ b/source/lldb.cpp @@ -31,6 +31,8 @@ #include "Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h" #include "Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h" #include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h" +#include "Plugins/ABI/SysV-ppc/ABISysV_ppc.h" +#include "Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h" #include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h" #include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" #include "Plugins/Instruction/ARM/EmulateInstructionARM.h" @@ -81,6 +83,8 @@ #endif #if defined (_WIN32) +#include "lldb/Host/windows/windows.h" +#include "Plugins/Process/Windows/DynamicLoaderWindows.h" #include "Plugins/Process/Windows/ProcessWindows.h" #endif @@ -92,6 +96,8 @@ #include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" #include "Plugins/Process/gdb-remote/ProcessGDBRemote.h" #include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" +#include "Plugins/MemoryHistory/asan/MemoryHistoryASan.h" +#include "Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h" using namespace lldb; using namespace lldb_private; @@ -113,6 +119,25 @@ lldb_private::Initialize () if (!g_inited) { g_inited = true; + +#if defined(_MSC_VER) + 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")) + { + // This will prevent Windows from displaying a dialog box requiring user interaction when + // LLDB crashes. This is mostly useful when automating LLDB, for example via the test + // suite, so that a crash in LLDB does not prevent completion of the test suite. + ::SetErrorMode(GetErrorMode() | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); + + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + } +#endif + Log::Initialize(); HostInfo::Initialize(); Timer::Initialize (); @@ -130,6 +155,8 @@ lldb_private::Initialize () ABIMacOSX_arm::Initialize(); ABIMacOSX_arm64::Initialize(); ABISysV_x86_64::Initialize(); + ABISysV_ppc::Initialize(); + ABISysV_ppc64::Initialize(); DisassemblerLLVMC::Initialize(); ObjectContainerBSDArchive::Initialize(); ObjectFileELF::Initialize(); @@ -154,6 +181,8 @@ lldb_private::Initialize () #endif JITLoaderGDB::Initialize(); ProcessElfCore::Initialize(); + MemoryHistoryASan::Initialize(); + AddressSanitizerRuntime::Initialize(); #if defined (__APPLE__) //---------------------------------------------------------------------- @@ -181,6 +210,7 @@ lldb_private::Initialize () ProcessLinux::Initialize(); #endif #if defined(_WIN32) + DynamicLoaderWindows::Initialize(); ProcessWindows::Initialize(); #endif #if defined (__FreeBSD__) @@ -221,6 +251,8 @@ lldb_private::Terminate () ABIMacOSX_arm::Terminate(); ABIMacOSX_arm64::Terminate(); ABISysV_x86_64::Terminate(); + ABISysV_ppc::Terminate(); + ABISysV_ppc64::Terminate(); DisassemblerLLVMC::Terminate(); ObjectContainerBSDArchive::Terminate(); ObjectFileELF::Terminate(); @@ -244,6 +276,8 @@ lldb_private::Terminate () #endif JITLoaderGDB::Terminate(); ProcessElfCore::Terminate(); + MemoryHistoryASan::Terminate(); + AddressSanitizerRuntime::Terminate(); #if defined (__APPLE__) DynamicLoaderMacOSXDYLD::Terminate(); @@ -264,6 +298,10 @@ lldb_private::Terminate () Debugger::SettingsTerminate (); +#if defined (_WIN32) + DynamicLoaderWindows::Terminate(); +#endif + #if defined (__linux__) ProcessLinux::Terminate(); #endif @@ -425,6 +463,7 @@ lldb_private::GetSectionTypeAsCString (SectionType sect_type) case eSectionTypeDWARFAppleNamespaces: return "apple-namespaces"; case eSectionTypeDWARFAppleObjC: return "apple-objc"; case eSectionTypeEHFrame: return "eh-frame"; + case eSectionTypeCompactUnwind: return "compact-unwind"; case eSectionTypeOther: return "regular"; } return "unknown"; diff --git a/tools/compact-unwind/compact-unwind-dumper.c b/tools/compact-unwind/compact-unwind-dumper.c new file mode 100644 index 000000000000..fd8ea2161896 --- /dev/null +++ b/tools/compact-unwind/compact-unwind-dumper.c @@ -0,0 +1,1215 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EXTRACT_BITS(value, mask) \ + ( (value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask)))-1) ) + + +// A quick sketch of a program which can parse the compact unwind info +// used on Darwin systems for exception handling. The output of +// unwinddump will be more authoritative/reliable but this program +// can dump at least the UNWIND_X86_64_MODE_RBP_FRAME format entries +// correctly. + +struct symbol +{ + uint64_t file_address; + const char *name; +}; + +int +symbol_compare (const void *a, const void *b) +{ + return (int) ((struct symbol *)a)->file_address - ((struct symbol *)b)->file_address; +} + +struct baton +{ + cpu_type_t cputype; + + uint8_t *mach_header_start; // pointer into this program's address space + uint8_t *compact_unwind_start; // pointer into this program's address space + + int addr_size; // 4 or 8 bytes, the size of addresses in this file + + uint64_t text_segment_vmaddr; // __TEXT segment vmaddr + uint64_t text_segment_file_offset; + + uint64_t text_section_vmaddr; // __TEXT,__text section vmaddr + uint64_t text_section_file_offset; + + uint64_t eh_section_file_address; // the file address of the __TEXT,__eh_frame section + + uint8_t *lsda_array_start; // for the currently-being-processed first-level index + uint8_t *lsda_array_end; // the lsda_array_start for the NEXT first-level index + + struct symbol *symbols; + int symbols_count; + + uint64_t *function_start_addresses; + int function_start_addresses_count; + + int current_index_table_number; + + struct unwind_info_section_header unwind_header; + struct unwind_info_section_header_index_entry first_level_index_entry; + struct unwind_info_compressed_second_level_page_header compressed_second_level_page_header; + struct unwind_info_regular_second_level_page_header regular_second_level_page_header; +}; + + +uint64_t +read_leb128 (uint8_t **offset) +{ + uint64_t result = 0; + int shift = 0; + while (1) + { + uint8_t byte = **offset; + *offset = *offset + 1; + result |= (byte & 0x7f) << shift; + if ((byte & 0x80) == 0) + break; + shift += 7; + } + + return result; +} + +// step through the load commands in a thin mach-o binary, +// find the cputype and the start of the __TEXT,__unwind_info +// section, return a pointer to that section or NULL if not found. + +static void +scan_macho_load_commands (struct baton *baton) +{ + struct symtab_command symtab_cmd; + uint64_t linkedit_segment_vmaddr; + uint64_t linkedit_segment_file_offset; + + baton->compact_unwind_start = 0; + + uint32_t *magic = (uint32_t *) baton->mach_header_start; + + if (*magic != MH_MAGIC && *magic != MH_MAGIC_64) + { + printf ("Unexpected magic number 0x%x in header, exiting.", *magic); + exit (1); + } + + bool is_64bit = false; + if (*magic == MH_MAGIC_64) + is_64bit = true; + + uint8_t *offset = baton->mach_header_start; + + struct mach_header mh; + memcpy (&mh, offset, sizeof (struct mach_header)); + if (is_64bit) + offset += sizeof (struct mach_header_64); + else + offset += sizeof (struct mach_header); + + if (is_64bit) + baton->addr_size = 8; + else + baton->addr_size = 4; + + baton->cputype = mh.cputype; + + uint8_t *start_of_load_commands = offset; + + uint32_t cur_cmd = 0; + while (cur_cmd < mh.ncmds && (offset - start_of_load_commands) < mh.sizeofcmds) + { + struct load_command lc; + uint32_t *lc_cmd = (uint32_t *) offset; + uint32_t *lc_cmdsize = (uint32_t *) offset + 1; + uint8_t *start_of_this_load_cmd = offset; + + if (*lc_cmd == LC_SEGMENT || *lc_cmd == LC_SEGMENT_64) + { + char segment_name[17]; + segment_name[0] = '\0'; + uint32_t nsects = 0; + uint64_t segment_offset = 0; + uint64_t segment_vmaddr = 0; + + if (*lc_cmd == LC_SEGMENT_64) + { + struct segment_command_64 seg; + memcpy (&seg, offset, sizeof (struct segment_command_64)); + memcpy (&segment_name, &seg.segname, 16); + segment_name[16] = '\0'; + nsects = seg.nsects; + segment_offset = seg.fileoff; + segment_vmaddr = seg.vmaddr; + offset += sizeof (struct segment_command_64); + if ((seg.flags & SG_PROTECTED_VERSION_1) == SG_PROTECTED_VERSION_1) + { + printf ("Segment '%s' is encrypted.\n", segment_name); + } + } + + if (*lc_cmd == LC_SEGMENT) + { + struct segment_command seg; + memcpy (&seg, offset, sizeof (struct segment_command)); + memcpy (&segment_name, &seg.segname, 16); + segment_name[16] = '\0'; + nsects = seg.nsects; + segment_offset = seg.fileoff; + segment_vmaddr = seg.vmaddr; + offset += sizeof (struct segment_command); + if ((seg.flags & SG_PROTECTED_VERSION_1) == SG_PROTECTED_VERSION_1) + { + printf ("Segment '%s' is encrypted.\n", segment_name); + } + } + + if (nsects != 0 && strcmp (segment_name, "__TEXT") == 0) + { + baton->text_segment_vmaddr = segment_vmaddr; + baton->text_segment_file_offset = segment_offset; + + uint32_t current_sect = 0; + while (current_sect < nsects && (offset - start_of_this_load_cmd) < *lc_cmdsize) + { + char sect_name[17]; + memcpy (§_name, offset, 16); + sect_name[16] = '\0'; + if (strcmp (sect_name, "__unwind_info") == 0) + { + if (is_64bit) + { + struct section_64 sect; + memcpy (§, offset, sizeof (struct section_64)); + baton->compact_unwind_start = baton->mach_header_start + sect.offset; + } + else + { + struct section sect; + memcpy (§, offset, sizeof (struct section)); + baton->compact_unwind_start = baton->mach_header_start + sect.offset; + } + } + if (strcmp (sect_name, "__eh_frame") == 0) + { + if (is_64bit) + { + struct section_64 sect; + memcpy (§, offset, sizeof (struct section_64)); + baton->eh_section_file_address = sect.addr; + } + else + { + struct section sect; + memcpy (§, offset, sizeof (struct section)); + baton->eh_section_file_address = sect.addr; + } + } + if (strcmp (sect_name, "__text") == 0) + { + if (is_64bit) + { + struct section_64 sect; + memcpy (§, offset, sizeof (struct section_64)); + baton->text_section_vmaddr = sect.addr; + baton->text_section_file_offset = sect.offset; + } + else + { + struct section sect; + memcpy (§, offset, sizeof (struct section)); + baton->text_section_vmaddr = sect.addr; + } + } + if (is_64bit) + { + offset += sizeof (struct section_64); + } + else + { + offset += sizeof (struct section); + } + } + } + + if (strcmp (segment_name, "__LINKEDIT") == 0) + { + linkedit_segment_vmaddr = segment_vmaddr; + linkedit_segment_file_offset = segment_offset; + } + } + + if (*lc_cmd == LC_SYMTAB) + { + memcpy (&symtab_cmd, offset, sizeof (struct symtab_command)); + } + + if (*lc_cmd == LC_DYSYMTAB) + { + struct dysymtab_command dysymtab_cmd; + memcpy (&dysymtab_cmd, offset, sizeof (struct dysymtab_command)); + + int nlist_size = 12; + if (is_64bit) + nlist_size = 16; + + char *string_table = (char *) (baton->mach_header_start + symtab_cmd.stroff); + uint8_t *local_syms = baton->mach_header_start + symtab_cmd.symoff + (dysymtab_cmd.ilocalsym * nlist_size); + int local_syms_count = dysymtab_cmd.nlocalsym; + uint8_t *exported_syms = baton->mach_header_start + symtab_cmd.symoff + (dysymtab_cmd.iextdefsym * nlist_size); + int exported_syms_count = dysymtab_cmd.nextdefsym; + + // We're only going to create records for a small number of these symbols but to + // simplify the memory management I'll allocate enough space to store all of them. + baton->symbols = (struct symbol *) malloc (sizeof (struct symbol) * (local_syms_count + exported_syms_count)); + baton->symbols_count = 0; + + for (int i = 0; i < local_syms_count; i++) + { + struct nlist_64 nlist; + if (is_64bit) + { + memcpy (&nlist, local_syms + (i * nlist_size), sizeof (struct nlist_64)); + } + else + { + struct nlist nlist_32; + memcpy (&nlist_32, local_syms + (i * nlist_size), sizeof (struct nlist)); + nlist.n_un.n_strx = nlist_32.n_un.n_strx; + nlist.n_type = nlist_32.n_type; + nlist.n_sect = nlist_32.n_sect; + nlist.n_desc = nlist_32.n_desc; + nlist.n_value = nlist_32.n_value; + } + if ((nlist.n_type & N_STAB) == 0 + && ((nlist.n_type & N_EXT) == 1 || + ((nlist.n_type & N_TYPE) == N_TYPE && nlist.n_sect != NO_SECT)) + && nlist.n_value != 0 + && nlist.n_value != baton->text_segment_vmaddr) + { + baton->symbols[baton->symbols_count].file_address = nlist.n_value; + baton->symbols[baton->symbols_count].name = string_table + nlist.n_un.n_strx; + baton->symbols_count++; + } + } + + for (int i = 0; i < exported_syms_count; i++) + { + struct nlist_64 nlist; + if (is_64bit) + { + memcpy (&nlist, exported_syms + (i * nlist_size), sizeof (struct nlist_64)); + } + else + { + struct nlist nlist_32; + memcpy (&nlist_32, exported_syms + (i * nlist_size), sizeof (struct nlist)); + nlist.n_un.n_strx = nlist_32.n_un.n_strx; + nlist.n_type = nlist_32.n_type; + nlist.n_sect = nlist_32.n_sect; + nlist.n_desc = nlist_32.n_desc; + nlist.n_value = nlist_32.n_value; + } + if ((nlist.n_type & N_STAB) == 0 + && ((nlist.n_type & N_EXT) == 1 || + ((nlist.n_type & N_TYPE) == N_TYPE && nlist.n_sect != NO_SECT)) + && nlist.n_value != 0 + && nlist.n_value != baton->text_segment_vmaddr) + { + baton->symbols[baton->symbols_count].file_address = nlist.n_value; + baton->symbols[baton->symbols_count].name = string_table + nlist.n_un.n_strx; + baton->symbols_count++; + } + } + + qsort (baton->symbols, baton->symbols_count, sizeof (struct symbol), symbol_compare); + } + + if (*lc_cmd == LC_FUNCTION_STARTS) + { + struct linkedit_data_command function_starts_cmd; + memcpy (&function_starts_cmd, offset, sizeof (struct linkedit_data_command)); + + uint8_t *funcstarts_offset = baton->mach_header_start + function_starts_cmd.dataoff; + uint8_t *function_end = funcstarts_offset + function_starts_cmd.datasize; + int count = 0; + + while (funcstarts_offset < function_end) + { + if (read_leb128 (&funcstarts_offset) != 0) + { + count++; + } + } + + baton->function_start_addresses = (uint64_t *) malloc (sizeof (uint64_t) * count); + baton->function_start_addresses_count = count; + + funcstarts_offset = baton->mach_header_start + function_starts_cmd.dataoff; + uint64_t current_pc = baton->text_segment_vmaddr; + int i = 0; + while (funcstarts_offset < function_end) + { + uint64_t func_start = read_leb128 (&funcstarts_offset); + if (func_start != 0) + { + current_pc += func_start; + baton->function_start_addresses[i++] = current_pc; + } + } + } + + offset = start_of_this_load_cmd + *lc_cmdsize; + cur_cmd++; + } + + + // Augment the symbol table with the function starts table -- adding symbol entries + // for functions that were stripped. + + int unnamed_functions_to_add = 0; + for (int i = 0; i < baton->function_start_addresses_count; i++) + { + struct symbol search_key; + search_key.file_address = baton->function_start_addresses[i]; + struct symbol *sym = bsearch (&search_key, baton->symbols, baton->symbols_count, sizeof (struct symbol), symbol_compare); + if (sym == NULL) + unnamed_functions_to_add++; + } + + baton->symbols = (struct symbol *) realloc (baton->symbols, sizeof (struct symbol) * (baton->symbols_count + unnamed_functions_to_add)); + + int current_unnamed_symbol = 1; + int number_symbols_added = 0; + for (int i = 0; i < baton->function_start_addresses_count; i++) + { + struct symbol search_key; + search_key.file_address = baton->function_start_addresses[i]; + struct symbol *sym = bsearch (&search_key, baton->symbols, baton->symbols_count, sizeof (struct symbol), symbol_compare); + if (sym == NULL) + { + char *name; + asprintf (&name, "unnamed function #%d", current_unnamed_symbol++); + baton->symbols[baton->symbols_count + number_symbols_added].file_address = baton->function_start_addresses[i]; + baton->symbols[baton->symbols_count + number_symbols_added].name = name; + number_symbols_added++; + } + } + baton->symbols_count += number_symbols_added; + qsort (baton->symbols, baton->symbols_count, sizeof (struct symbol), symbol_compare); + + +// printf ("function start addresses\n"); +// for (int i = 0; i < baton->function_start_addresses_count; i++) +// { +// printf ("0x%012llx\n", baton->function_start_addresses[i]); +// } + +// printf ("symbol table names & addresses\n"); +// for (int i = 0; i < baton->symbols_count; i++) +// { +// printf ("0x%012llx %s\n", baton->symbols[i].file_address, baton->symbols[i].name); +// } + +} + +void +print_encoding_x86_64 (struct baton baton, uint8_t *function_start, uint32_t encoding) +{ + int mode = encoding & UNWIND_X86_64_MODE_MASK; + switch (mode) + { + case UNWIND_X86_64_MODE_RBP_FRAME: + { + printf ("frame func: CFA is rbp+%d ", 16); + printf (" rip=[CFA-8] rbp=[CFA-16]"); + uint32_t saved_registers_offset = EXTRACT_BITS (encoding, UNWIND_X86_64_RBP_FRAME_OFFSET); + + uint32_t saved_registers_locations = EXTRACT_BITS (encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); + + + saved_registers_offset += 2; + + for (int i = 0; i < 5; i++) + { + switch (saved_registers_locations & 0x7) + { + case UNWIND_X86_64_REG_NONE: + break; + case UNWIND_X86_64_REG_RBX: + printf (" rbx=[CFA-%d]", saved_registers_offset * 8); + break; + case UNWIND_X86_64_REG_R12: + printf (" r12=[CFA-%d]", saved_registers_offset * 8); + break; + case UNWIND_X86_64_REG_R13: + printf (" r13=[CFA-%d]", saved_registers_offset * 8); + break; + case UNWIND_X86_64_REG_R14: + printf (" r14=[CFA-%d]", saved_registers_offset * 8); + break; + case UNWIND_X86_64_REG_R15: + printf (" r15=[CFA-%d]", saved_registers_offset * 8); + break; + } + saved_registers_offset--; + saved_registers_locations >>= 3; + } + } + break; + + case UNWIND_X86_64_MODE_STACK_IND: + case UNWIND_X86_64_MODE_STACK_IMMD: + { + uint32_t stack_size = EXTRACT_BITS (encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); + uint32_t register_count = EXTRACT_BITS (encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); + uint32_t permutation = EXTRACT_BITS (encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); + + if (mode == UNWIND_X86_64_MODE_STACK_IND && function_start) + { + uint32_t stack_adjust = EXTRACT_BITS (encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); + + // offset into the function instructions; 0 == beginning of first instruction + uint32_t offset_to_subl_insn = EXTRACT_BITS (encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); + + stack_size = *((uint32_t*) (function_start + offset_to_subl_insn)); + + stack_size += stack_adjust * 8; + + printf ("large stack "); + } + + printf ("frameless function: stack size %d, register count %d ", stack_size * 8, register_count); + + if (register_count == 0) + { + printf (" no registers saved"); + } + else + { + + // We need to include (up to) 6 registers in 10 bits. + // That would be 18 bits if we just used 3 bits per reg to indicate + // the order they're saved on the stack. + // + // This is done with Lehmer code permutation, e.g. see + // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms + int permunreg[6]; + + // This decodes the variable-base number in the 10 bits + // and gives us the Lehmer code sequence which can then + // be decoded. + + switch (register_count) + { + case 6: + permunreg[0] = permutation/120; // 120 == 5! + permutation -= (permunreg[0]*120); + permunreg[1] = permutation/24; // 24 == 4! + permutation -= (permunreg[1]*24); + permunreg[2] = permutation/6; // 6 == 3! + permutation -= (permunreg[2]*6); + permunreg[3] = permutation/2; // 2 == 2! + permutation -= (permunreg[3]*2); + permunreg[4] = permutation; // 1 == 1! + permunreg[5] = 0; + break; + case 5: + permunreg[0] = permutation/120; + permutation -= (permunreg[0]*120); + permunreg[1] = permutation/24; + permutation -= (permunreg[1]*24); + permunreg[2] = permutation/6; + permutation -= (permunreg[2]*6); + permunreg[3] = permutation/2; + permutation -= (permunreg[3]*2); + permunreg[4] = permutation; + break; + case 4: + permunreg[0] = permutation/60; + permutation -= (permunreg[0]*60); + permunreg[1] = permutation/12; + permutation -= (permunreg[1]*12); + permunreg[2] = permutation/3; + permutation -= (permunreg[2]*3); + permunreg[3] = permutation; + break; + case 3: + permunreg[0] = permutation/20; + permutation -= (permunreg[0]*20); + permunreg[1] = permutation/4; + permutation -= (permunreg[1]*4); + permunreg[2] = permutation; + break; + case 2: + permunreg[0] = permutation/5; + permutation -= (permunreg[0]*5); + permunreg[1] = permutation; + break; + case 1: + permunreg[0] = permutation; + break; + } + + // Decode the Lehmer code for this permutation of + // the registers v. http://en.wikipedia.org/wiki/Lehmer_code + + int registers[6]; + bool used[7] = { false, false, false, false, false, false, false }; + for (int i = 0; i < register_count; i++) + { + int renum = 0; + for (int j = 1; j < 7; j++) + { + if (used[j] == false) + { + if (renum == permunreg[i]) + { + registers[i] = j; + used[j] = true; + break; + } + renum++; + } + } + } + + + printf (" CFA is rsp+%d ", stack_size * 8); + + uint32_t saved_registers_offset = 1; + printf (" rip=[CFA-%d]", saved_registers_offset * 8); + saved_registers_offset++; + + for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--) + { + switch (registers[i]) + { + case UNWIND_X86_64_REG_NONE: + break; + case UNWIND_X86_64_REG_RBX: + printf (" rbx=[CFA-%d]", saved_registers_offset * 8); + break; + case UNWIND_X86_64_REG_R12: + printf (" r12=[CFA-%d]", saved_registers_offset * 8); + break; + case UNWIND_X86_64_REG_R13: + printf (" r13=[CFA-%d]", saved_registers_offset * 8); + break; + case UNWIND_X86_64_REG_R14: + printf (" r14=[CFA-%d]", saved_registers_offset * 8); + break; + case UNWIND_X86_64_REG_R15: + printf (" r15=[CFA-%d]", saved_registers_offset * 8); + break; + case UNWIND_X86_64_REG_RBP: + printf (" rbp=[CFA-%d]", saved_registers_offset * 8); + break; + } + saved_registers_offset++; + } + + } + + } + break; + + case UNWIND_X86_64_MODE_DWARF: + { + uint32_t dwarf_offset = encoding & UNWIND_X86_DWARF_SECTION_OFFSET; + printf ("DWARF unwind instructions: FDE at offset %d (file address 0x%" PRIx64 ")", + dwarf_offset, dwarf_offset + baton.eh_section_file_address); + } + break; + + case 0: + { + printf (" no unwind information"); + } + break; + } +} + +void +print_encoding_i386 (struct baton baton, uint8_t *function_start, uint32_t encoding) +{ + int mode = encoding & UNWIND_X86_MODE_MASK; + switch (mode) + { + case UNWIND_X86_MODE_EBP_FRAME: + { + printf ("frame func: CFA is ebp+%d ", 8); + printf (" eip=[CFA-4] ebp=[CFA-8]"); + uint32_t saved_registers_offset = EXTRACT_BITS (encoding, UNWIND_X86_EBP_FRAME_OFFSET); + + uint32_t saved_registers_locations = EXTRACT_BITS (encoding, UNWIND_X86_EBP_FRAME_REGISTERS); + + + saved_registers_offset += 2; + + for (int i = 0; i < 5; i++) + { + switch (saved_registers_locations & 0x7) + { + case UNWIND_X86_REG_NONE: + break; + case UNWIND_X86_REG_EBX: + printf (" ebx=[CFA-%d]", saved_registers_offset * 4); + break; + case UNWIND_X86_REG_ECX: + printf (" ecx=[CFA-%d]", saved_registers_offset * 4); + break; + case UNWIND_X86_REG_EDX: + printf (" edx=[CFA-%d]", saved_registers_offset * 4); + break; + case UNWIND_X86_REG_EDI: + printf (" edi=[CFA-%d]", saved_registers_offset * 4); + break; + case UNWIND_X86_REG_ESI: + printf (" esi=[CFA-%d]", saved_registers_offset * 4); + break; + } + saved_registers_offset--; + saved_registers_locations >>= 3; + } + } + break; + + case UNWIND_X86_MODE_STACK_IND: + case UNWIND_X86_MODE_STACK_IMMD: + { + uint32_t stack_size = EXTRACT_BITS (encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); + uint32_t register_count = EXTRACT_BITS (encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT); + uint32_t permutation = EXTRACT_BITS (encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION); + + if (mode == UNWIND_X86_MODE_STACK_IND && function_start) + { + uint32_t stack_adjust = EXTRACT_BITS (encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST); + + // offset into the function instructions; 0 == beginning of first instruction + uint32_t offset_to_subl_insn = EXTRACT_BITS (encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); + + stack_size = *((uint32_t*) (function_start + offset_to_subl_insn)); + + stack_size += stack_adjust * 4; + + printf ("large stack "); + } + + printf ("frameless function: stack size %d, register count %d ", stack_size * 4, register_count); + + if (register_count == 0) + { + printf (" no registers saved"); + } + else + { + + // We need to include (up to) 6 registers in 10 bits. + // That would be 18 bits if we just used 3 bits per reg to indicate + // the order they're saved on the stack. + // + // This is done with Lehmer code permutation, e.g. see + // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms + int permunreg[6]; + + // This decodes the variable-base number in the 10 bits + // and gives us the Lehmer code sequence which can then + // be decoded. + + switch (register_count) + { + case 6: + permunreg[0] = permutation/120; // 120 == 5! + permutation -= (permunreg[0]*120); + permunreg[1] = permutation/24; // 24 == 4! + permutation -= (permunreg[1]*24); + permunreg[2] = permutation/6; // 6 == 3! + permutation -= (permunreg[2]*6); + permunreg[3] = permutation/2; // 2 == 2! + permutation -= (permunreg[3]*2); + permunreg[4] = permutation; // 1 == 1! + permunreg[5] = 0; + break; + case 5: + permunreg[0] = permutation/120; + permutation -= (permunreg[0]*120); + permunreg[1] = permutation/24; + permutation -= (permunreg[1]*24); + permunreg[2] = permutation/6; + permutation -= (permunreg[2]*6); + permunreg[3] = permutation/2; + permutation -= (permunreg[3]*2); + permunreg[4] = permutation; + break; + case 4: + permunreg[0] = permutation/60; + permutation -= (permunreg[0]*60); + permunreg[1] = permutation/12; + permutation -= (permunreg[1]*12); + permunreg[2] = permutation/3; + permutation -= (permunreg[2]*3); + permunreg[3] = permutation; + break; + case 3: + permunreg[0] = permutation/20; + permutation -= (permunreg[0]*20); + permunreg[1] = permutation/4; + permutation -= (permunreg[1]*4); + permunreg[2] = permutation; + break; + case 2: + permunreg[0] = permutation/5; + permutation -= (permunreg[0]*5); + permunreg[1] = permutation; + break; + case 1: + permunreg[0] = permutation; + break; + } + + // Decode the Lehmer code for this permutation of + // the registers v. http://en.wikipedia.org/wiki/Lehmer_code + + int registers[6]; + bool used[7] = { false, false, false, false, false, false, false }; + for (int i = 0; i < register_count; i++) + { + int renum = 0; + for (int j = 1; j < 7; j++) + { + if (used[j] == false) + { + if (renum == permunreg[i]) + { + registers[i] = j; + used[j] = true; + break; + } + renum++; + } + } + } + + + printf (" CFA is esp+%d ", stack_size * 4); + + uint32_t saved_registers_offset = 1; + printf (" eip=[CFA-%d]", saved_registers_offset * 4); + saved_registers_offset++; + + for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--) + { + switch (registers[i]) + { + case UNWIND_X86_REG_NONE: + break; + case UNWIND_X86_REG_EBX: + printf (" ebx=[CFA-%d]", saved_registers_offset * 4); + break; + case UNWIND_X86_REG_ECX: + printf (" ecx=[CFA-%d]", saved_registers_offset * 4); + break; + case UNWIND_X86_REG_EDX: + printf (" edx=[CFA-%d]", saved_registers_offset * 4); + break; + case UNWIND_X86_REG_EDI: + printf (" edi=[CFA-%d]", saved_registers_offset * 4); + break; + case UNWIND_X86_REG_ESI: + printf (" esi=[CFA-%d]", saved_registers_offset * 4); + break; + case UNWIND_X86_REG_EBP: + printf (" ebp=[CFA-%d]", saved_registers_offset * 4); + break; + } + saved_registers_offset++; + } + + } + + } + break; + + case UNWIND_X86_MODE_DWARF: + { + uint32_t dwarf_offset = encoding & UNWIND_X86_DWARF_SECTION_OFFSET; + printf ("DWARF unwind instructions: FDE at offset %d (file address 0x%" PRIx64 ")", + dwarf_offset, dwarf_offset + baton.eh_section_file_address); + } + break; + + case 0: + { + printf (" no unwind information"); + } + break; + } +} + + +void print_encoding (struct baton baton, uint8_t *function_start, uint32_t encoding) +{ + + if (baton.cputype == CPU_TYPE_X86_64) + { + print_encoding_x86_64 (baton, function_start, encoding); + } + else if (baton.cputype == CPU_TYPE_I386) + { + print_encoding_i386 (baton, function_start, encoding); + } + else + { + printf (" -- unsupported encoding arch -- "); + } +} + +void +print_function_encoding (struct baton baton, uint32_t idx, uint32_t encoding, uint32_t entry_encoding_index, uint32_t entry_func_offset) +{ + + char *entry_encoding_index_str = ""; + if (entry_encoding_index != (uint32_t) -1) + { + asprintf (&entry_encoding_index_str, ", encoding #%d", entry_encoding_index); + } + else + { + asprintf (&entry_encoding_index_str, ""); + } + + uint64_t file_address = baton.first_level_index_entry.functionOffset + entry_func_offset + baton.text_segment_vmaddr; + + printf (" func [%d] offset %d (file addr 0x%" PRIx64 ")%s, encoding is 0x%x", + idx, entry_func_offset, + file_address, + entry_encoding_index_str, + encoding); + + struct symbol *symbol = NULL; + for (int i = 0; i < baton.symbols_count; i++) + { + if (i == baton.symbols_count - 1 && baton.symbols[i].file_address <= file_address) + { + symbol = &(baton.symbols[i]); + break; + } + else + { + if (baton.symbols[i].file_address <= file_address && baton.symbols[i + 1].file_address > file_address) + { + symbol = &(baton.symbols[i]); + break; + } + } + } + + printf ("\n "); + if (symbol) + { + int offset = file_address - symbol->file_address; + + // FIXME this is a poor heuristic - if we're greater than 16 bytes past the + // start of the function, this is the unwind info for a stripped function. + // In reality the compact unwind entry may not line up exactly with the + // function bounds. + if (offset >= 0) + { + printf ("name: %s", symbol->name); + if (offset > 0) + { + printf (" + %d", offset); + } + } + printf ("\n "); + } + + print_encoding (baton, baton.mach_header_start + baton.first_level_index_entry.functionOffset + baton.text_section_file_offset + entry_func_offset, encoding); + + bool has_lsda = encoding & UNWIND_HAS_LSDA; + + if (has_lsda) + { + uint32_t func_offset = entry_func_offset + baton.first_level_index_entry.functionOffset; + + int lsda_entry_number = -1; + + uint32_t low = 0; + uint32_t high = (baton.lsda_array_end - baton.lsda_array_start) / sizeof (struct unwind_info_section_header_lsda_index_entry); + + while (low < high) + { + uint32_t mid = (low + high) / 2; + + uint8_t *mid_lsda_entry_addr = (baton.lsda_array_start + (mid * sizeof (struct unwind_info_section_header_lsda_index_entry))); + struct unwind_info_section_header_lsda_index_entry mid_lsda_entry; + memcpy (&mid_lsda_entry, mid_lsda_entry_addr, sizeof (struct unwind_info_section_header_lsda_index_entry)); + if (mid_lsda_entry.functionOffset == func_offset) + { + lsda_entry_number = (mid_lsda_entry_addr - baton.lsda_array_start) / sizeof (struct unwind_info_section_header_lsda_index_entry); + break; + } + else if (mid_lsda_entry.functionOffset < func_offset) + { + low = mid + 1; + } + else + { + high = mid; + } + } + + if (lsda_entry_number != -1) + { + printf (", LSDA entry #%d", lsda_entry_number); + } + else + { + printf (", LSDA entry not found"); + } + } + + uint32_t pers_idx = EXTRACT_BITS (encoding, UNWIND_PERSONALITY_MASK); + if (pers_idx != 0) + { + pers_idx--; // Change 1-based to 0-based index + printf (", personality entry #%d", pers_idx); + } + + printf ("\n"); +} + +void +print_second_level_index_regular (struct baton baton) +{ + uint8_t *page_entries = baton.compact_unwind_start + baton.first_level_index_entry.secondLevelPagesSectionOffset + baton.regular_second_level_page_header.entryPageOffset; + uint32_t entries_count = baton.regular_second_level_page_header.entryCount; + + uint8_t *offset = page_entries; + + uint32_t idx = 0; + while (idx < entries_count) + { + uint32_t func_offset = *((uint32_t *) (offset)); + uint32_t encoding = *((uint32_t *) (offset + 4)); + + // UNWIND_SECOND_LEVEL_REGULAR entries have a funcOffset which includes the + // functionOffset from the containing index table already. UNWIND_SECOND_LEVEL_COMPRESSED + // entries only have the offset from the containing index table functionOffset. + // So strip off the contianing index table functionOffset value here so they can + // be treated the same at the lower layers. + + print_function_encoding (baton, idx, encoding, (uint32_t) -1, func_offset - baton.first_level_index_entry.functionOffset); + idx++; + offset += 8; + } +} + +void +print_second_level_index_compressed (struct baton baton) +{ + uint8_t *this_index = baton.compact_unwind_start + baton.first_level_index_entry.secondLevelPagesSectionOffset; + uint8_t *start_of_entries = this_index + baton.compressed_second_level_page_header.entryPageOffset; + uint8_t *offset = start_of_entries; + for (uint16_t idx = 0; idx < baton.compressed_second_level_page_header.entryCount; idx++) + { + uint32_t entry = *((uint32_t*) offset); + offset += 4; + uint32_t encoding; + + uint32_t entry_encoding_index = UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX (entry); + uint32_t entry_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (entry); + + if (entry_encoding_index < baton.unwind_header.commonEncodingsArrayCount) + { + // encoding is in common table in section header + encoding = *((uint32_t*) (baton.compact_unwind_start + baton.unwind_header.commonEncodingsArraySectionOffset + (entry_encoding_index * sizeof (uint32_t)))); + } + else + { + // encoding is in page specific table + uint32_t page_encoding_index = entry_encoding_index - baton.unwind_header.commonEncodingsArrayCount; + encoding = *((uint32_t*) (this_index + baton.compressed_second_level_page_header.encodingsPageOffset + (page_encoding_index * sizeof (uint32_t)))); + } + + + print_function_encoding (baton, idx, encoding, entry_encoding_index, entry_func_offset); + } +} + +void +print_second_level_index (struct baton baton) +{ + uint8_t *index_start = baton.compact_unwind_start + baton.first_level_index_entry.secondLevelPagesSectionOffset; + + if ((*(uint32_t*) index_start) == UNWIND_SECOND_LEVEL_REGULAR) + { + struct unwind_info_regular_second_level_page_header header; + memcpy (&header, index_start, sizeof (struct unwind_info_regular_second_level_page_header)); + printf (" UNWIND_SECOND_LEVEL_REGULAR #%d entryPageOffset %d, entryCount %d\n", baton.current_index_table_number, header.entryPageOffset, header.entryCount); + baton.regular_second_level_page_header = header; + print_second_level_index_regular (baton); + } + + if ((*(uint32_t*) index_start) == UNWIND_SECOND_LEVEL_COMPRESSED) + { + struct unwind_info_compressed_second_level_page_header header; + memcpy (&header, index_start, sizeof (struct unwind_info_compressed_second_level_page_header)); + printf (" UNWIND_SECOND_LEVEL_COMPRESSED #%d entryPageOffset %d, entryCount %d, encodingsPageOffset %d, encodingsCount %d\n", baton.current_index_table_number, header.entryPageOffset, header.entryCount, header.encodingsPageOffset, header.encodingsCount); + baton.compressed_second_level_page_header = header; + print_second_level_index_compressed (baton); + } +} + + +void +print_index_sections (struct baton baton) +{ + uint8_t *index_section_offset = baton.compact_unwind_start + baton.unwind_header.indexSectionOffset; + uint32_t index_count = baton.unwind_header.indexCount; + + uint32_t cur_idx = 0; + + uint8_t *offset = index_section_offset; + while (cur_idx < index_count) + { + baton.current_index_table_number = cur_idx; + struct unwind_info_section_header_index_entry index_entry; + memcpy (&index_entry, offset, sizeof (struct unwind_info_section_header_index_entry)); + printf ("index section #%d: functionOffset %d, secondLevelPagesSectionOffset %d, lsdaIndexArraySectionOffset %d\n", cur_idx, index_entry.functionOffset, index_entry.secondLevelPagesSectionOffset, index_entry.lsdaIndexArraySectionOffset); + + // secondLevelPagesSectionOffset == 0 means this is a sentinel entry + if (index_entry.secondLevelPagesSectionOffset != 0) + { + struct unwind_info_section_header_index_entry next_index_entry; + memcpy (&next_index_entry, offset + sizeof (struct unwind_info_section_header_index_entry), sizeof (struct unwind_info_section_header_index_entry)); + + baton.lsda_array_start = baton.compact_unwind_start + index_entry.lsdaIndexArraySectionOffset; + baton.lsda_array_end = baton.compact_unwind_start + next_index_entry.lsdaIndexArraySectionOffset; + + uint8_t *lsda_entry_offset = baton.lsda_array_start; + uint32_t lsda_count = 0; + while (lsda_entry_offset < baton.lsda_array_end) + { + struct unwind_info_section_header_lsda_index_entry lsda_entry; + memcpy (&lsda_entry, lsda_entry_offset, sizeof (struct unwind_info_section_header_lsda_index_entry)); + uint64_t function_file_address = baton.first_level_index_entry.functionOffset + lsda_entry.functionOffset + baton.text_segment_vmaddr; + uint64_t lsda_file_address = lsda_entry.lsdaOffset + baton.text_segment_vmaddr; + printf (" LSDA [%d] functionOffset %d (%d) (file address 0x%" PRIx64 "), lsdaOffset %d (file address 0x%" PRIx64 ")\n", + lsda_count, lsda_entry.functionOffset, + lsda_entry.functionOffset - index_entry.functionOffset, + function_file_address, + lsda_entry.lsdaOffset, lsda_file_address); + lsda_count++; + lsda_entry_offset += sizeof (struct unwind_info_section_header_lsda_index_entry); + } + + printf ("\n"); + + baton.first_level_index_entry = index_entry; + print_second_level_index (baton); + } + + printf ("\n"); + + cur_idx++; + offset += sizeof (struct unwind_info_section_header_index_entry); + } +} + +int main (int argc, char **argv) +{ + struct stat st; + char *file = argv[0]; + if (argc > 1) + file = argv[1]; + int fd = open (file, O_RDONLY); + if (fd == -1) + { + printf ("Failed to open '%s'\n", file); + exit (1); + } + fstat (fd, &st); + uint8_t *file_mem = (uint8_t*) mmap (0, st.st_size, PROT_READ, MAP_PRIVATE | MAP_FILE, fd, 0); + if (file_mem == MAP_FAILED) + { + printf ("Failed to mmap() '%s'\n", file); + } + + FILE *f = fopen ("a.out", "r"); + + struct baton baton; + baton.mach_header_start = file_mem; + baton.symbols = NULL; + baton.symbols_count = 0; + baton.function_start_addresses = NULL; + baton.function_start_addresses_count = 0; + + scan_macho_load_commands (&baton); + + if (baton.compact_unwind_start == NULL) + { + printf ("could not find __TEXT,__unwind_info section\n"); + exit (1); + } + + + struct unwind_info_section_header header; + memcpy (&header, baton.compact_unwind_start, sizeof (struct unwind_info_section_header)); + printf ("Header:\n"); + printf (" version %u\n", header.version); + printf (" commonEncodingsArraySectionOffset is %d\n", header.commonEncodingsArraySectionOffset); + printf (" commonEncodingsArrayCount is %d\n", header.commonEncodingsArrayCount); + printf (" personalityArraySectionOffset is %d\n", header.personalityArraySectionOffset); + printf (" personalityArrayCount is %d\n", header.personalityArrayCount); + printf (" indexSectionOffset is %d\n", header.indexSectionOffset); + printf (" indexCount is %d\n", header.indexCount); + + uint8_t *common_encodings = baton.compact_unwind_start + header.commonEncodingsArraySectionOffset; + uint32_t encoding_idx = 0; + while (encoding_idx < header.commonEncodingsArrayCount) + { + uint32_t encoding = *((uint32_t*) common_encodings); + printf (" Common Encoding [%d]: 0x%x ", encoding_idx, encoding); + print_encoding (baton, NULL, encoding); + printf ("\n"); + common_encodings += sizeof (uint32_t); + encoding_idx++; + } + + uint8_t *pers_arr = baton.compact_unwind_start + header.personalityArraySectionOffset; + uint32_t pers_idx = 0; + while (pers_idx < header.personalityArrayCount) + { + int32_t pers_delta = *((int32_t*) (baton.compact_unwind_start + header.personalityArraySectionOffset + (pers_idx * sizeof (uint32_t)))); + printf (" Personality [%d]: personality function ptr @ offset %d (file address 0x%" PRIx64 ")\n", pers_idx, pers_delta, baton.text_segment_vmaddr + pers_delta); + pers_idx++; + pers_arr += sizeof (uint32_t); + } + + printf ("\n"); + + baton.unwind_header = header; + + print_index_sections (baton); + + + return 0; +} diff --git a/tools/driver/Driver.cpp b/tools/driver/Driver.cpp index 854310031c37..f02b081b8f0f 100644 --- a/tools/driver/Driver.cpp +++ b/tools/driver/Driver.cpp @@ -19,6 +19,8 @@ #if defined(_WIN32) #include #include +#elif defined(__ANDROID_NDK__) +#include #else #include #endif @@ -39,6 +41,10 @@ #include "lldb/API/SBThread.h" #include "lldb/API/SBProcess.h" +#if !defined(__APPLE__) +#include "llvm/Support/DataTypes.h" +#endif + using namespace lldb; static void reset_stdin_termios (); @@ -104,8 +110,15 @@ static OptionDefinition g_options[] = "Tells the debugger to read in and execute the lldb commands in the given file, before any file provided on the command line has been loaded." }, { LLDB_3_TO_5, false, "one-line-before-file" , 'O', required_argument, 0, eArgTypeNone, "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." }, + { LLDB_3_TO_5, false, "one-line-on-crash" , 'k', required_argument, 0, eArgTypeNone, + "When in batch mode, tells the debugger to execute this one-line lldb command if the target crashes." }, + { LLDB_3_TO_5, false, "source-on-crash" , 'K', required_argument, 0, eArgTypeFilename, + "When in batch mode, tells the debugger to source this file of lldb commands if the target crashes." }, { LLDB_3_TO_5, false, "source-quietly" , 'Q', no_argument , 0, eArgTypeNone, - "Tells the debugger suppress output from commands provided in the -s, -S, -O and -o commands." }, + "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." }, + { LLDB_3_TO_5, false, "batch" , 'b', no_argument , 0, eArgTypeNone, + "Tells the debugger to running the commands from -s, -S, -o & -O, and then quit. However if any run command stopped due to a signal or crash, " + "the debugger will return to the interactive prompt at the place of the crash." }, { LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0, eArgTypeNone, "Tells the debugger to open source files using the host's \"external editor\" mechanism." }, { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone, @@ -393,6 +406,7 @@ Driver::OptionData::OptionData () : m_crash_log (), m_initial_commands (), m_after_file_commands (), + m_after_crash_commands(), m_debug_mode (false), m_source_quietly(false), m_print_version (false), @@ -402,6 +416,7 @@ Driver::OptionData::OptionData () : m_process_name(), m_process_pid(LLDB_INVALID_PROCESS_ID), m_use_external_editor(false), + m_batch(false), m_seen_options() { } @@ -417,6 +432,16 @@ Driver::OptionData::Clear () m_script_lang = lldb::eScriptLanguageDefault; m_initial_commands.clear (); m_after_file_commands.clear (); + // If there is a local .lldbinit, source that: + SBFileSpec local_lldbinit("./.lldbinit", true); + if (local_lldbinit.Exists()) + { + char path[2048]; + local_lldbinit.GetPath(path, 2047); + InitialCmdEntry entry(path, true, true); + m_after_file_commands.push_back (entry); + } + m_debug_mode = false; m_source_quietly = false; m_print_help = false; @@ -425,35 +450,45 @@ Driver::OptionData::Clear () m_use_external_editor = false; m_wait_for = false; m_process_name.erase(); + m_batch = false; + m_after_crash_commands.clear(); + m_process_pid = LLDB_INVALID_PROCESS_ID; } void -Driver::OptionData::AddInitialCommand (const char *command, bool before_file, bool is_file, SBError &error) +Driver::OptionData::AddInitialCommand (const char *command, CommandPlacement placement, bool is_file, bool silent, SBError &error) { - std::vector > *command_set; - if (before_file) + std::vector *command_set; + switch (placement) + { + case eCommandPlacementBeforeFile: command_set = &(m_initial_commands); - else + break; + case eCommandPlacementAfterFile: command_set = &(m_after_file_commands); + break; + case eCommandPlacementAfterCrash: + command_set = &(m_after_crash_commands); + break; + } if (is_file) { SBFileSpec file(command); if (file.Exists()) - command_set->push_back (std::pair (true, optarg)); + command_set->push_back (InitialCmdEntry(command, is_file, silent)); else if (file.ResolveExecutableLocation()) { char final_path[PATH_MAX]; file.GetPath (final_path, sizeof(final_path)); - std::string path_str (final_path); - command_set->push_back (std::pair (true, path_str)); + command_set->push_back (InitialCmdEntry(final_path, is_file, silent)); } else error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg); } else - command_set->push_back (std::pair (false, optarg)); + command_set->push_back (InitialCmdEntry(command, is_file, silent)); } void @@ -485,16 +520,30 @@ Driver::GetScriptLanguage() const } void -Driver::WriteInitialCommands (bool before_file, SBStream &strm) +Driver::WriteCommandsForSourcing (CommandPlacement placement, SBStream &strm) { - std::vector > &command_set = before_file ? m_option_data.m_initial_commands : - m_option_data.m_after_file_commands; + std::vector *command_set; + switch (placement) + { + case eCommandPlacementBeforeFile: + command_set = &m_option_data.m_initial_commands; + break; + case eCommandPlacementAfterFile: + command_set = &m_option_data.m_after_file_commands; + break; + case eCommandPlacementAfterCrash: + command_set = &m_option_data.m_after_crash_commands; + break; + } - for (const auto &command_pair : command_set) + for (const auto &command_entry : *command_set) { - const char *command = command_pair.second.c_str(); - if (command_pair.first) - strm.Printf("command source -s %i '%s'\n", m_option_data.m_source_quietly, command); + const char *command = command_entry.contents.c_str(); + if (command_entry.is_file) + { + bool source_quietly = m_option_data.m_source_quietly || command_entry.source_quietly; + strm.Printf("command source -s %i '%s'\n", source_quietly, command); + } else strm.Printf("%s\n", command); } @@ -637,6 +686,10 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) m_option_data.m_print_python_path = true; break; + case 'b': + m_option_data.m_batch = true; + break; + case 'c': { SBFileSpec file(optarg); @@ -697,6 +750,13 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) m_option_data.m_source_quietly = true; break; + case 'K': + m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterCrash, true, true, error); + break; + case 'k': + m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterCrash, false, true, error); + break; + case 'n': m_option_data.m_process_name = optarg; break; @@ -715,16 +775,16 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) } break; case 's': - m_option_data.AddInitialCommand(optarg, false, true, error); + m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterFile, true, true, error); break; case 'o': - m_option_data.AddInitialCommand(optarg, false, false, error); + m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterFile, false, true, error); break; case 'S': - m_option_data.AddInitialCommand(optarg, true, true, error); + m_option_data.AddInitialCommand(optarg, eCommandPlacementBeforeFile, true, true, error); break; case 'O': - m_option_data.AddInitialCommand(optarg, true, false, error); + m_option_data.AddInitialCommand(optarg, eCommandPlacementBeforeFile, false, true, error); break; default: m_option_data.m_print_help = true; @@ -807,6 +867,95 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) return error; } +static ::FILE * +PrepareCommandsForSourcing (const char *commands_data, size_t commands_size, int fds[2]) +{ + enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE + + bool success = true; + ::FILE *commands_file = NULL; + fds[0] = -1; + fds[1] = -1; + int err = 0; +#ifdef _WIN32 + err = _pipe(fds, commands_size, O_BINARY); +#else + err = pipe(fds); +#endif + if (err == 0) + { + ssize_t nrwr = write(fds[WRITE], commands_data, commands_size); + if (nrwr < 0) + { + fprintf(stderr, "error: write(%i, %p, %zd) failed (errno = %i) " + "when trying to open LLDB commands pipe\n", + fds[WRITE], commands_data, commands_size, errno); + success = false; + } + else if (static_cast(nrwr) == commands_size) + { + // Close the write end of the pipe so when we give the read end to + // the debugger/command interpreter it will exit when it consumes all + // of the data +#ifdef _WIN32 + _close(fds[WRITE]); fds[WRITE] = -1; +#else + close(fds[WRITE]); fds[WRITE] = -1; +#endif + // Now open the read file descriptor in a FILE * that we can give to + // the debugger as an input handle + commands_file = fdopen(fds[READ], "r"); + if (commands_file) + { + fds[READ] = -1; // The FILE * 'commands_file' now owns the read descriptor + // Hand ownership if the FILE * over to the debugger for "commands_file". + } + else + { + fprintf(stderr, + "error: fdopen(%i, \"r\") failed (errno = %i) when " + "trying to open LLDB commands pipe\n", + fds[READ], errno); + success = false; + } + } + } + else + { + fprintf(stderr, "error: can't create pipe file descriptors for LLDB commands\n"); + success = false; + } + + return commands_file; +} + +void +CleanupAfterCommandSourcing (int fds[2]) +{ + enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE + + // Close any pipes that we still have ownership of + if ( fds[WRITE] != -1) + { +#ifdef _WIN32 + _close(fds[WRITE]); fds[WRITE] = -1; +#else + close(fds[WRITE]); fds[WRITE] = -1; +#endif + + } + + if ( fds[READ] != -1) + { +#ifdef _WIN32 + _close(fds[READ]); fds[READ] = -1; +#else + close(fds[READ]); fds[READ] = -1; +#endif + } + +} + void Driver::MainLoop () { @@ -849,7 +998,7 @@ Driver::MainLoop () SBStream commands_stream; // First source in the commands specified to be run before the file arguments are processed. - WriteInitialCommands(true, commands_stream); + WriteCommandsForSourcing(eCommandPlacementBeforeFile, commands_stream); const size_t num_args = m_option_data.m_args.size(); if (num_args > 0) @@ -899,11 +1048,8 @@ Driver::MainLoop () commands_stream.Printf ("process attach --pid %" PRIu64 "\n", m_option_data.m_process_pid); } - WriteInitialCommands(false, commands_stream); + WriteCommandsForSourcing(eCommandPlacementAfterFile, commands_stream); - // Now that all option parsing is done, we try and parse the .lldbinit - // file in the current working directory - sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result); if (GetDebugMode()) { result.PutError(m_debugger.GetErrorFileHandle()); @@ -917,72 +1063,69 @@ Driver::MainLoop () // so we can then run the command interpreter using the file contents. const char *commands_data = commands_stream.GetData(); const size_t commands_size = commands_stream.GetSize(); + + // The command file might have requested that we quit, this variable will track that. + bool quit_requested = false; + bool stopped_for_crash = false; if (commands_data && commands_size) { - enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE - + int initial_commands_fds[2]; bool success = true; - int fds[2] = { -1, -1 }; - int err = 0; -#ifdef _WIN32 - err = _pipe(fds, commands_size, O_BINARY); -#else - err = pipe(fds); -#endif - if (err == 0) + FILE *commands_file = PrepareCommandsForSourcing (commands_data, commands_size, initial_commands_fds); + if (commands_file) { - if (write (fds[WRITE], commands_data, commands_size) == commands_size) + m_debugger.SetInputFileHandle (commands_file, true); + + // Set the debugger into Sync mode when running the command file. Otherwise command files + // that run the target won't run in a sensible way. + bool old_async = m_debugger.GetAsync(); + m_debugger.SetAsync(false); + int num_errors; + + SBCommandInterpreterRunOptions options; + options.SetStopOnError (true); + if (m_option_data.m_batch) + options.SetStopOnCrash (true); + + m_debugger.RunCommandInterpreter(handle_events, + spawn_thread, + options, + num_errors, + quit_requested, + stopped_for_crash); + + if (m_option_data.m_batch && stopped_for_crash && !m_option_data.m_after_crash_commands.empty()) { - // Close the write end of the pipe so when we give the read end to - // the debugger/command interpreter it will exit when it consumes all - // of the data -#ifdef _WIN32 - _close(fds[WRITE]); fds[WRITE] = -1; -#else - close(fds[WRITE]); fds[WRITE] = -1; -#endif - // Now open the read file descriptor in a FILE * that we can give to - // the debugger as an input handle - FILE *commands_file = fdopen(fds[READ], "r"); + int crash_command_fds[2]; + SBStream crash_commands_stream; + WriteCommandsForSourcing (eCommandPlacementAfterCrash, crash_commands_stream); + const char *crash_commands_data = crash_commands_stream.GetData(); + const size_t crash_commands_size = crash_commands_stream.GetSize(); + commands_file = PrepareCommandsForSourcing (crash_commands_data, crash_commands_size, crash_command_fds); if (commands_file) { - fds[READ] = -1; // The FILE * 'commands_file' now owns the read descriptor - // Hand ownership if the FILE * over to the debugger for "commands_file". + bool local_quit_requested; + bool local_stopped_for_crash; m_debugger.SetInputFileHandle (commands_file, true); - m_debugger.RunCommandInterpreter(handle_events, spawn_thread); - } - else - { - fprintf(stderr, "error: fdopen(%i, \"r\") failed (errno = %i) when trying to open LLDB commands pipe\n", fds[READ], errno); - success = false; + + m_debugger.RunCommandInterpreter(handle_events, + spawn_thread, + options, + num_errors, + local_quit_requested, + local_stopped_for_crash); + if (local_quit_requested) + quit_requested = true; + } } + m_debugger.SetAsync(old_async); } else - { - fprintf(stderr, "error: can't create pipe file descriptors for LLDB commands\n"); success = false; - } // Close any pipes that we still have ownership of - if ( fds[WRITE] != -1) - { -#ifdef _WIN32 - _close(fds[WRITE]); fds[WRITE] = -1; -#else - close(fds[WRITE]); fds[WRITE] = -1; -#endif - - } - - if ( fds[READ] != -1) - { -#ifdef _WIN32 - _close(fds[READ]); fds[READ] = -1; -#else - close(fds[READ]); fds[READ] = -1; -#endif - } + CleanupAfterCommandSourcing(initial_commands_fds); // Something went wrong with command pipe if (!success) @@ -995,8 +1138,18 @@ Driver::MainLoop () // Now set the input file handle to STDIN and run the command // interpreter again in interactive mode and let the debugger // take ownership of stdin - m_debugger.SetInputFileHandle (stdin, true); - m_debugger.RunCommandInterpreter(handle_events, spawn_thread); + + bool go_interactive = true; + if (quit_requested) + go_interactive = false; + else if (m_option_data.m_batch && !stopped_for_crash) + go_interactive = false; + + if (go_interactive) + { + m_debugger.SetInputFileHandle (stdin, true); + m_debugger.RunCommandInterpreter(handle_events, spawn_thread); + } reset_stdin_termios(); fclose (stdin); diff --git a/tools/driver/Driver.h b/tools/driver/Driver.h index 8b6c6eebdd56..38b125481d92 100644 --- a/tools/driver/Driver.h +++ b/tools/driver/Driver.h @@ -28,6 +28,13 @@ class IOChannel; class Driver : public lldb::SBBroadcaster { public: + typedef enum CommandPlacement + { + eCommandPlacementBeforeFile, + eCommandPlacementAfterFile, + eCommandPlacementAfterCrash, + } CommandPlacement; + Driver (); virtual @@ -52,7 +59,7 @@ public: GetScriptLanguage() const; void - WriteInitialCommands (bool before_file, lldb::SBStream &strm); + WriteCommandsForSourcing (CommandPlacement placement, lldb::SBStream &strm); bool GetDebugMode() const; @@ -68,16 +75,30 @@ public: Clear(); void - AddInitialCommand (const char *command, bool before_file, bool is_file, lldb::SBError &error); + AddInitialCommand (const char *command, CommandPlacement placement, bool is_file, bool quietly, lldb::SBError &error); //static OptionDefinition m_cmd_option_table[]; + struct InitialCmdEntry + { + InitialCmdEntry (const char *in_contents, bool in_is_file, bool in_quiet = false) : + contents (in_contents), + is_file (in_is_file), + source_quietly(in_quiet) + {} + + std::string contents; + bool is_file; + bool source_quietly; + }; + std::vector m_args; lldb::ScriptLanguage m_script_lang; std::string m_core_file; std::string m_crash_log; - std::vector > m_initial_commands; - std::vector > m_after_file_commands; + std::vector m_initial_commands; + std::vector m_after_file_commands; + std::vector m_after_crash_commands; bool m_debug_mode; bool m_source_quietly; bool m_print_version; @@ -87,6 +108,7 @@ public: std::string m_process_name; lldb::pid_t m_process_pid; bool m_use_external_editor; // FIXME: When we have set/show variables we can remove this from here. + bool m_batch; typedef std::set OptionSet; OptionSet m_seen_options; }; diff --git a/tools/driver/Platform.h b/tools/driver/Platform.h index e26610711aca..8995512a0f8f 100644 --- a/tools/driver/Platform.h +++ b/tools/driver/Platform.h @@ -101,15 +101,17 @@ #include #include - #include #include #include - #if defined(__FreeBSD__) || defined(__NetBSD__) - #include - #else - #include - #endif +#if !defined(__ANDROID_NDK__) + #include + #if defined(__FreeBSD__) || defined(__NetBSD__) + #include + #else + #include + #endif +#endif #endif diff --git a/tools/lldb-mi/Driver.cpp b/tools/lldb-mi/Driver.cpp index a59b4b74eb0a..34a2471e9672 100644 --- a/tools/lldb-mi/Driver.cpp +++ b/tools/lldb-mi/Driver.cpp @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include @@ -41,22 +41,22 @@ using namespace lldb; -static void reset_stdin_termios (); +static void reset_stdin_termios(); static bool g_old_stdin_termios_is_valid = false; static struct termios g_old_stdin_termios; -static char *g_debugger_name = (char *) ""; +static char *g_debugger_name = (char *)""; Driver *g_driver = NULL; // In the Driver::MainLoop, we change the terminal settings. This function is // added as an atexit handler to make sure we clean them up. static void -reset_stdin_termios () +reset_stdin_termios() { if (g_old_stdin_termios_is_valid) { g_old_stdin_termios_is_valid = false; - ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios); + ::tcsetattr(STDIN_FILENO, TCSANOW, &g_old_stdin_termios); } } @@ -65,99 +65,94 @@ typedef struct uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0 // then this option belongs to option set n. bool required; // This option is required (in the current usage level) - const char * long_option; // Full name for this option. + const char *long_option; // Full name for this option. int short_option; // Single character for this option. int option_has_arg; // no_argument, required_argument or optional_argument uint32_t completion_type; // Cookie the option class can use to do define the argument completion. lldb::CommandArgumentType argument_type; // Type of argument this option takes - const char * usage_text; // Full text explaining what this options does and what (if any) argument to + const char *usage_text; // Full text explaining what this options does and what (if any) argument to // pass it. } OptionDefinition; -#define LLDB_3_TO_5 LLDB_OPT_SET_3|LLDB_OPT_SET_4|LLDB_OPT_SET_5 -#define LLDB_4_TO_5 LLDB_OPT_SET_4|LLDB_OPT_SET_5 - -static OptionDefinition g_options[] = -{ - { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , 0, eArgTypeNone, - "Prints out the usage information for the LLDB debugger." }, - { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , 0, eArgTypeNone, - "Prints out the current version number of the LLDB debugger." }, - { LLDB_OPT_SET_3, true , "arch" , 'a', required_argument, 0, eArgTypeArchitecture, - "Tells the debugger to use the specified architecture when starting and running the program. must " - "be one of the architectures for which the program was compiled." }, - { LLDB_OPT_SET_3, true , "file" , 'f', required_argument, 0, eArgTypeFilename, - "Tells the debugger to use the file as the program to be debugged." }, - { LLDB_OPT_SET_3, false, "core" , 'c', required_argument, 0, eArgTypeFilename, - "Tells the debugger to use the fullpath to as the core file." }, - { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, 0, eArgTypePid, - "Tells the debugger to attach to a process with the given pid." }, - { LLDB_OPT_SET_4, true , "attach-name" , 'n', required_argument, 0, eArgTypeProcessName, - "Tells the debugger to attach to a process with the given name." }, - { LLDB_OPT_SET_4, true , "wait-for" , 'w', no_argument , 0, eArgTypeNone, - "Tells the debugger to wait for a process with the given pid or name to launch before attaching." }, - { LLDB_3_TO_5, false, "source" , 's', required_argument, 0, eArgTypeFilename, - "Tells the debugger to read in and execute the lldb commands in the given file, after any file provided on the command line has been loaded." }, - { LLDB_3_TO_5, false, "one-line" , 'o', required_argument, 0, eArgTypeNone, - "Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded." }, - { LLDB_3_TO_5, false, "source-before-file" , 'S', required_argument, 0, eArgTypeFilename, - "Tells the debugger to read in and execute the lldb commands in the given file, before any file provided on the command line has been loaded." }, - { LLDB_3_TO_5, false, "one-line-before-file" , 'O', required_argument, 0, eArgTypeNone, - "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." }, - { LLDB_3_TO_5, false, "source-quietly" , 'Q', no_argument , 0, eArgTypeNone, - "Tells the debugger suppress output from commands provided in the -s, -S, -O and -o commands." }, - { LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0, eArgTypeNone, - "Tells the debugger to open source files using the host's \"external editor\" mechanism." }, - { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone, - "Do not automatically parse any '.lldbinit' files." }, - { LLDB_3_TO_5, false, "no-use-colors" , 'X', no_argument , 0, eArgTypeNone, - "Do not use colors." }, - { LLDB_OPT_SET_6, true , "python-path" , 'P', no_argument , 0, eArgTypeNone, - "Prints out the path to the lldb.py file for this version of lldb." }, - { LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0, eArgTypeScriptLang, - "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. " - "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python " - "extensions have been implemented." }, - { LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone, - "Tells the debugger to print out extra information for debugging itself." }, - { 0, false, NULL , 0 , 0 , 0, eArgTypeNone, NULL } -}; +#define LLDB_3_TO_5 LLDB_OPT_SET_3 | LLDB_OPT_SET_4 | LLDB_OPT_SET_5 +#define LLDB_4_TO_5 LLDB_OPT_SET_4 | LLDB_OPT_SET_5 + +static OptionDefinition g_options[] = { + {LLDB_OPT_SET_1, true, "help", 'h', no_argument, 0, eArgTypeNone, "Prints out the usage information for the LLDB debugger."}, + {LLDB_OPT_SET_2, true, "version", 'v', no_argument, 0, eArgTypeNone, "Prints out the current version number of the LLDB debugger."}, + {LLDB_OPT_SET_3, true, "arch", 'a', required_argument, 0, eArgTypeArchitecture, + "Tells the debugger to use the specified architecture when starting and running the program. must " + "be one of the architectures for which the program was compiled."}, + {LLDB_OPT_SET_3, true, "file", 'f', required_argument, 0, eArgTypeFilename, + "Tells the debugger to use the file as the program to be debugged."}, + {LLDB_OPT_SET_3, false, "core", 'c', required_argument, 0, eArgTypeFilename, + "Tells the debugger to use the fullpath to as the core file."}, + {LLDB_OPT_SET_5, true, "attach-pid", 'p', required_argument, 0, eArgTypePid, + "Tells the debugger to attach to a process with the given pid."}, + {LLDB_OPT_SET_4, true, "attach-name", 'n', required_argument, 0, eArgTypeProcessName, + "Tells the debugger to attach to a process with the given name."}, + {LLDB_OPT_SET_4, true, "wait-for", 'w', no_argument, 0, eArgTypeNone, + "Tells the debugger to wait for a process with the given pid or name to launch before attaching."}, + {LLDB_3_TO_5, false, "source", 's', required_argument, 0, eArgTypeFilename, "Tells the debugger to read in and execute the lldb " + "commands in the given file, after any file provided on " + "the command line has been loaded."}, + {LLDB_3_TO_5, false, "one-line", 'o', required_argument, 0, eArgTypeNone, + "Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded."}, + {LLDB_3_TO_5, false, "source-before-file", 'S', required_argument, 0, eArgTypeFilename, + "Tells the debugger to read in and execute the lldb commands in the given file, before any file provided on the command line has been " + "loaded."}, + {LLDB_3_TO_5, false, "one-line-before-file", 'O', required_argument, 0, eArgTypeNone, + "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded."}, + {LLDB_3_TO_5, false, "source-quietly", 'Q', no_argument, 0, eArgTypeNone, + "Tells the debugger suppress output from commands provided in the -s, -S, -O and -o commands."}, + {LLDB_3_TO_5, false, "editor", 'e', no_argument, 0, eArgTypeNone, + "Tells the debugger to open source files using the host's \"external editor\" mechanism."}, + {LLDB_3_TO_5, false, "no-lldbinit", 'x', no_argument, 0, eArgTypeNone, "Do not automatically parse any '.lldbinit' files."}, + {LLDB_3_TO_5, false, "no-use-colors", 'X', no_argument, 0, eArgTypeNone, "Do not use colors."}, + {LLDB_OPT_SET_6, true, "python-path", 'P', no_argument, 0, eArgTypeNone, + "Prints out the path to the lldb.py file for this version of lldb."}, + {LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0, eArgTypeScriptLang, + "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. " + "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python " + "extensions have been implemented."}, + {LLDB_3_TO_5, false, "debug", 'd', no_argument, 0, eArgTypeNone, + "Tells the debugger to print out extra information for debugging itself."}, + {0, false, NULL, 0, 0, 0, eArgTypeNone, NULL}}; static const uint32_t last_option_set_with_args = 2; -Driver::Driver () : - SBBroadcaster ("Driver"), - m_debugger (SBDebugger::Create(false)), - m_option_data () +Driver::Driver() + : SBBroadcaster("Driver") + , m_debugger(SBDebugger::Create(false)) + , m_option_data() { // We want to be able to handle CTRL+D in the terminal to have it terminate // certain input - m_debugger.SetCloseInputOnEOF (false); - g_debugger_name = (char *) m_debugger.GetInstanceName(); + m_debugger.SetCloseInputOnEOF(false); + g_debugger_name = (char *)m_debugger.GetInstanceName(); if (g_debugger_name == NULL) - g_debugger_name = (char *) ""; + g_debugger_name = (char *)""; g_driver = this; } -Driver::~Driver () +Driver::~Driver() { g_driver = NULL; g_debugger_name = NULL; } - // This function takes INDENT, which tells how many spaces to output at the front -// of each line; TEXT, which is the text that is to be output. It outputs the -// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the -// front of each line. It breaks lines on spaces, tabs or newlines, shortening -// the line if necessary to not break in the middle of a word. It assumes that +// of each line; TEXT, which is the text that is to be output. It outputs the +// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the +// front of each line. It breaks lines on spaces, tabs or newlines, shortening +// the line if necessary to not break in the middle of a word. It assumes that // each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters. void -OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns) +OutputFormattedUsageText(FILE *out, int indent, const char *text, int output_max_columns) { - int len = strlen (text); - std::string text_string (text); + int len = strlen(text); + std::string text_string(text); // Force indentation to be reasonable. if (indent >= output_max_columns) @@ -167,7 +162,7 @@ OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_ma if (len + indent < output_max_columns) // Output as a single line - fprintf (out, "%*s%s\n", indent, "", text); + fprintf(out, "%*s%s\n", indent, "", text); else { // We need to break it up into multiple lines. @@ -179,39 +174,37 @@ OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_ma while (end < final_end) { - // Dont start the 'text' on a space, since we're already outputting the indentation. - while ((start < final_end) && (text[start] == ' ')) - start++; - - end = start + text_width; - if (end > final_end) - end = final_end; - else - { - // If we're not at the end of the text, make sure we break the line on white space. - while (end > start - && text[end] != ' ' && text[end] != '\t' && text[end] != '\n') - end--; - } - sub_len = end - start; - std::string substring = text_string.substr (start, sub_len); - fprintf (out, "%*s%s\n", indent, "", substring.c_str()); - start = end + 1; + // Dont start the 'text' on a space, since we're already outputting the indentation. + while ((start < final_end) && (text[start] == ' ')) + start++; + + end = start + text_width; + if (end > final_end) + end = final_end; + else + { + // If we're not at the end of the text, make sure we break the line on white space. + while (end > start && text[end] != ' ' && text[end] != '\t' && text[end] != '\n') + end--; + } + sub_len = end - start; + std::string substring = text_string.substr(start, sub_len); + fprintf(out, "%*s%s\n", indent, "", substring.c_str()); + start = end + 1; } } } void -ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data) +ShowUsage(FILE *out, OptionDefinition *option_table, Driver::OptionData data) { uint32_t screen_width = 80; uint32_t indent_level = 0; const char *name = "lldb"; - - fprintf (out, "\nUsage:\n\n"); - indent_level += 2; + fprintf(out, "\nUsage:\n\n"); + indent_level += 2; // First, show each usage level set of options, e.g. [options-for-level-0] // [options-for-level-1] @@ -219,7 +212,7 @@ ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data) uint32_t num_options; uint32_t num_option_sets = 0; - + for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options) { uint32_t this_usage_mask = option_table[num_options].usage_mask; @@ -244,50 +237,50 @@ ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data) for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++) { uint32_t opt_set_mask; - + opt_set_mask = 1 << opt_set; - + if (opt_set > 0) - fprintf (out, "\n"); - fprintf (out, "%*s%s", indent_level, "", name); + fprintf(out, "\n"); + fprintf(out, "%*s%s", indent_level, "", name); bool is_help_line = false; - + for (uint32_t i = 0; i < num_options; ++i) { if (option_table[i].usage_mask & opt_set_mask) { CommandArgumentType arg_type = option_table[i].argument_type; - const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type); + const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString(arg_type); // This is a bit of a hack, but there's no way to say certain options don't have arguments yet... // so we do it by hand here. if (option_table[i].short_option == 'h') is_help_line = true; - + if (option_table[i].required) { if (option_table[i].option_has_arg == required_argument) - fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name); + fprintf(out, " -%c <%s>", option_table[i].short_option, arg_name); else if (option_table[i].option_has_arg == optional_argument) - fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name); + fprintf(out, " -%c [<%s>]", option_table[i].short_option, arg_name); else - fprintf (out, " -%c", option_table[i].short_option); + fprintf(out, " -%c", option_table[i].short_option); } else { if (option_table[i].option_has_arg == required_argument) - fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name); + fprintf(out, " [-%c <%s>]", option_table[i].short_option, arg_name); else if (option_table[i].option_has_arg == optional_argument) - fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name); + fprintf(out, " [-%c [<%s>]]", option_table[i].short_option, arg_name); else - fprintf (out, " [-%c]", option_table[i].short_option); + fprintf(out, " [-%c]", option_table[i].short_option); } } } if (!is_help_line && (opt_set <= last_option_set_with_args)) - fprintf (out, " [[--] [ ...]]"); + fprintf(out, " [[--] [ ...]]"); } - fprintf (out, "\n\n"); + fprintf(out, "\n\n"); // Now print out all the detailed information about the various options: long form, short form and help text: // -- long_name @@ -305,55 +298,47 @@ ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data) for (uint32_t i = 0; i < num_options; ++i) { // Only print this option if we haven't already seen it. - pos = options_seen.find (option_table[i].short_option); + pos = options_seen.find(option_table[i].short_option); if (pos == options_seen.end()) { CommandArgumentType arg_type = option_table[i].argument_type; - const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type); + const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString(arg_type); - options_seen.insert (option_table[i].short_option); - fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option); + options_seen.insert(option_table[i].short_option); + fprintf(out, "%*s-%c ", indent_level, "", option_table[i].short_option); if (arg_type != eArgTypeNone) - fprintf (out, "<%s>", arg_name); - fprintf (out, "\n"); - fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option); + fprintf(out, "<%s>", arg_name); + fprintf(out, "\n"); + fprintf(out, "%*s--%s ", indent_level, "", option_table[i].long_option); if (arg_type != eArgTypeNone) - fprintf (out, "<%s>", arg_name); - fprintf (out, "\n"); + fprintf(out, "<%s>", arg_name); + fprintf(out, "\n"); indent_level += 5; - OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width); + OutputFormattedUsageText(out, indent_level, option_table[i].usage_text, screen_width); indent_level -= 5; - fprintf (out, "\n"); + fprintf(out, "\n"); } } indent_level -= 5; - - fprintf (out, "\n%*sNotes:\n", - indent_level, ""); + + fprintf(out, "\n%*sNotes:\n", indent_level, ""); indent_level += 5; - - fprintf (out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will be processed from left to right in order, " - "\n%*swith the source files and commands interleaved. The same is true of the \"-S\" and \"-O\" options." - "\n%*sThe before file and after file sets can intermixed freely, the command parser will sort them out." - "\n%*sThe order of the file specifiers (\"-c\", \"-f\", etc.) is not significant in this regard.\n\n", - indent_level, "", - indent_level, "", - indent_level, "", - indent_level, ""); - - fprintf (out, "\n%*sIf you don't provide -f then the first argument will be the file to be debugged" - "\n%*swhich means that '%s -- [ []]' also works." - "\n%*sBut remember to end the options with \"--\" if any of your arguments have a \"-\" in them.\n\n", - indent_level, "", - indent_level, "", - name, - indent_level, ""); + + fprintf(out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will be processed from left to right in order, " + "\n%*swith the source files and commands interleaved. The same is true of the \"-S\" and \"-O\" options." + "\n%*sThe before file and after file sets can intermixed freely, the command parser will sort them out." + "\n%*sThe order of the file specifiers (\"-c\", \"-f\", etc.) is not significant in this regard.\n\n", + indent_level, "", indent_level, "", indent_level, "", indent_level, ""); + + fprintf(out, "\n%*sIf you don't provide -f then the first argument will be the file to be debugged" + "\n%*swhich means that '%s -- [ []]' also works." + "\n%*sBut remember to end the options with \"--\" if any of your arguments have a \"-\" in them.\n\n", + indent_level, "", indent_level, "", name, indent_level, ""); } void -BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector &getopt_table, - uint32_t num_options) +BuildGetOptTable(OptionDefinition *expanded_option_table, std::vector &getopt_table, uint32_t num_options) { if (num_options == 0) return; @@ -362,61 +347,60 @@ BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector option_seen; - getopt_table.resize (num_options + 1); + getopt_table.resize(num_options + 1); for (i = 0, j = 0; i < num_options; ++i) { char short_opt = expanded_option_table[i].short_option; - + if (option_seen.test(short_opt) == false) { - getopt_table[j].name = expanded_option_table[i].long_option; + getopt_table[j].name = expanded_option_table[i].long_option; getopt_table[j].has_arg = expanded_option_table[i].option_has_arg; - getopt_table[j].flag = NULL; - getopt_table[j].val = expanded_option_table[i].short_option; + getopt_table[j].flag = NULL; + getopt_table[j].val = expanded_option_table[i].short_option; option_seen.set(short_opt); ++j; } } - getopt_table[j].name = NULL; + getopt_table[j].name = NULL; getopt_table[j].has_arg = 0; - getopt_table[j].flag = NULL; - getopt_table[j].val = 0; - + getopt_table[j].flag = NULL; + getopt_table[j].val = 0; } -Driver::OptionData::OptionData () : - m_args(), - m_script_lang (lldb::eScriptLanguageDefault), - m_core_file (), - m_crash_log (), - m_initial_commands (), - m_after_file_commands (), - m_debug_mode (false), - m_source_quietly(false), - m_print_version (false), - m_print_python_path (false), - m_print_help (false), - m_wait_for(false), - m_process_name(), - m_process_pid(LLDB_INVALID_PROCESS_ID), - m_use_external_editor(false), - m_seen_options() +Driver::OptionData::OptionData() + : m_args() + , m_script_lang(lldb::eScriptLanguageDefault) + , m_core_file() + , m_crash_log() + , m_initial_commands() + , m_after_file_commands() + , m_debug_mode(false) + , m_source_quietly(false) + , m_print_version(false) + , m_print_python_path(false) + , m_print_help(false) + , m_wait_for(false) + , m_process_name() + , m_process_pid(LLDB_INVALID_PROCESS_ID) + , m_use_external_editor(false) + , m_seen_options() { } -Driver::OptionData::~OptionData () +Driver::OptionData::~OptionData() { } void -Driver::OptionData::Clear () +Driver::OptionData::Clear() { - m_args.clear (); + m_args.clear(); m_script_lang = lldb::eScriptLanguageDefault; - m_initial_commands.clear (); - m_after_file_commands.clear (); + m_initial_commands.clear(); + m_after_file_commands.clear(); m_debug_mode = false; m_source_quietly = false; m_print_help = false; @@ -429,9 +413,9 @@ Driver::OptionData::Clear () } void -Driver::OptionData::AddInitialCommand (const char *command, bool before_file, bool is_file, SBError &error) +Driver::OptionData::AddInitialCommand(const char *command, bool before_file, bool is_file, SBError &error) { - std::vector > *command_set; + std::vector> *command_set; if (before_file) command_set = &(m_initial_commands); else @@ -441,25 +425,25 @@ Driver::OptionData::AddInitialCommand (const char *command, bool before_file, bo { SBFileSpec file(command); if (file.Exists()) - command_set->push_back (std::pair (true, optarg)); + command_set->push_back(std::pair(true, optarg)); else if (file.ResolveExecutableLocation()) { char final_path[PATH_MAX]; - file.GetPath (final_path, sizeof(final_path)); - std::string path_str (final_path); - command_set->push_back (std::pair (true, path_str)); + file.GetPath(final_path, sizeof(final_path)); + std::string path_str(final_path); + command_set->push_back(std::pair(true, path_str)); } else error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg); } else - command_set->push_back (std::pair (false, optarg)); + command_set->push_back(std::pair(false, optarg)); } void -Driver::ResetOptionValues () +Driver::ResetOptionValues() { - m_option_data.Clear (); + m_option_data.Clear(); } const char * @@ -485,15 +469,15 @@ Driver::GetScriptLanguage() const } void -Driver::ExecuteInitialCommands (bool before_file) +Driver::ExecuteInitialCommands(bool before_file) { size_t num_commands; - std::vector > *command_set; + std::vector> *command_set; if (before_file) command_set = &(m_option_data.m_initial_commands); else command_set = &(m_option_data.m_after_file_commands); - + num_commands = command_set->size(); SBCommandReturnObject result; bool old_async = GetDebugger().GetAsync(); @@ -507,11 +491,11 @@ Driver::ExecuteInitialCommands (bool before_file) const char *executed_command = command; if (is_file) { - ::snprintf (command_string, sizeof(command_string), "command source -s %i '%s'", m_option_data.m_source_quietly, command); + ::snprintf(command_string, sizeof(command_string), "command source -s %i '%s'", m_option_data.m_source_quietly, command); executed_command = command_string; } - - m_debugger.GetCommandInterpreter().HandleCommand (executed_command, result, false); + + m_debugger.GetCommandInterpreter().HandleCommand(executed_command, result, false); if (!m_option_data.m_source_quietly || result.Succeeded() == false) { const size_t output_size = result.GetOutputSize(); @@ -519,17 +503,17 @@ Driver::ExecuteInitialCommands (bool before_file) { const char *cstr = result.GetOutput(dump_stream_only_if_no_immediate); if (cstr) - printf ("%s", cstr); + printf("%s", cstr); } const size_t error_size = result.GetErrorSize(); if (error_size > 0) { const char *cstr = result.GetError(dump_stream_only_if_no_immediate); if (cstr) - printf ("%s", cstr); + printf("%s", cstr); } } - + if (result.Succeeded() == false) { const char *type = before_file ? "before file" : "after_file"; @@ -550,16 +534,15 @@ Driver::GetDebugMode() const return m_option_data.m_debug_mode; } - // Check the arguments that were passed to this program to make sure they are valid and to get their // argument values (if any). Return a boolean value indicating whether or not to start up the full // debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR // if the user only wanted help or version information. SBError -Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) +Driver::ParseArgs(int argc, const char *argv[], FILE *out_fh, bool &exiting) { - ResetOptionValues (); + ResetOptionValues(); SBCommandReturnObject result; @@ -575,11 +558,11 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) if (num_options == 0) { if (argc > 1) - error.SetErrorStringWithFormat ("invalid number of options"); + error.SetErrorStringWithFormat("invalid number of options"); return error; } - BuildGetOptTable (g_options, long_options_vector, num_options); + BuildGetOptTable(g_options, long_options_vector, num_options); if (long_options_vector.empty()) long_options = NULL; @@ -588,7 +571,7 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) if (long_options == NULL) { - error.SetErrorStringWithFormat ("invalid long options"); + error.SetErrorStringWithFormat("invalid long options"); return error; } @@ -598,17 +581,17 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) { if (long_options[i].flag == NULL) { - option_string.push_back ((char) long_options[i].val); + option_string.push_back((char)long_options[i].val); switch (long_options[i].has_arg) { default: case no_argument: break; case required_argument: - option_string.push_back (':'); + option_string.push_back(':'); break; case optional_argument: - option_string.append ("::"); + option_string.append("::"); break; } } @@ -619,11 +602,11 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) // Driver constructor, then set the flags back to "read them in" here, and then if we see the // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the // main loop. - - m_debugger.SkipLLDBInitFiles (false); - m_debugger.SkipAppInitFiles (false); - // Prepare for & make calls to getopt_long_only. + m_debugger.SkipLLDBInitFiles(false); + m_debugger.SkipAppInitFiles(false); + +// Prepare for & make calls to getopt_long_only. #if __GLIBC__ optind = 0; #else @@ -634,26 +617,24 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) while (1) { int long_options_index = -1; - val = ::getopt_long_only (argc, const_cast(argv), option_string.c_str(), long_options, &long_options_index); + val = ::getopt_long_only(argc, const_cast(argv), option_string.c_str(), long_options, &long_options_index); if (val == -1) break; else if (val == '?') { m_option_data.m_print_help = true; - error.SetErrorStringWithFormat ("unknown or ambiguous option"); + error.SetErrorStringWithFormat("unknown or ambiguous option"); break; } else if (val == 0) continue; else { - m_option_data.m_seen_options.insert ((char) val); + m_option_data.m_seen_options.insert((char)val); if (long_options_index == -1) { - for (int i = 0; - long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val; - ++i) + for (int i = 0; long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val; ++i) { if (long_options[i].val == val) { @@ -682,55 +663,55 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) break; case 'c': + { + SBFileSpec file(optarg); + if (file.Exists()) { - SBFileSpec file(optarg); - if (file.Exists()) - { - m_option_data.m_core_file = optarg; - } - else - error.SetErrorStringWithFormat("file specified in --core (-c) option doesn't exist: '%s'", optarg); + m_option_data.m_core_file = optarg; } - break; - + else + error.SetErrorStringWithFormat("file specified in --core (-c) option doesn't exist: '%s'", optarg); + } + break; + case 'e': m_option_data.m_use_external_editor = true; break; case 'x': - m_debugger.SkipLLDBInitFiles (true); - m_debugger.SkipAppInitFiles (true); + m_debugger.SkipLLDBInitFiles(true); + m_debugger.SkipAppInitFiles(true); break; case 'X': - m_debugger.SetUseColor (false); + m_debugger.SetUseColor(false); break; case 'f': + { + SBFileSpec file(optarg); + if (file.Exists()) { - SBFileSpec file(optarg); - if (file.Exists()) - { - m_option_data.m_args.push_back (optarg); - } - else if (file.ResolveExecutableLocation()) - { - char path[PATH_MAX]; - file.GetPath (path, sizeof(path)); - m_option_data.m_args.push_back (path); - } - else - error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg); + m_option_data.m_args.push_back(optarg); } - break; + else if (file.ResolveExecutableLocation()) + { + char path[PATH_MAX]; + file.GetPath(path, sizeof(path)); + m_option_data.m_args.push_back(path); + } + else + error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg); + } + break; case 'a': - if (!m_debugger.SetDefaultArchitecture (optarg)) + if (!m_debugger.SetDefaultArchitecture(optarg)) error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg); break; case 'l': - m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg); + m_option_data.m_script_lang = m_debugger.GetScriptingLanguage(optarg); break; case 'd': @@ -744,20 +725,19 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) case 'n': m_option_data.m_process_name = optarg; break; - + case 'w': m_option_data.m_wait_for = true; break; - + case 'p': - { - char *remainder; - m_option_data.m_process_pid = strtol (optarg, &remainder, 0); - if (remainder == optarg || *remainder != '\0') - error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.", - optarg); - } - break; + { + char *remainder; + m_option_data.m_process_pid = strtol(optarg, &remainder, 0); + if (remainder == optarg || *remainder != '\0') + error.SetErrorStringWithFormat("Could not convert process PID: \"%s\" into a pid.", optarg); + } + break; case 's': m_option_data.AddInitialCommand(optarg, false, true, error); break; @@ -772,13 +752,13 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) break; default: m_option_data.m_print_help = true; - error.SetErrorStringWithFormat ("unrecognized option %c", short_option); + error.SetErrorStringWithFormat("unrecognized option %c", short_option); break; } } else { - error.SetErrorStringWithFormat ("invalid option with value %i", val); + error.SetErrorStringWithFormat("invalid option with value %i", val); } if (error.Fail()) { @@ -786,15 +766,15 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) } } } - + if (error.Fail() || m_option_data.m_print_help) { - ShowUsage (out_fh, g_options, m_option_data); + ShowUsage(out_fh, g_options, m_option_data); exiting = true; } else if (m_option_data.m_print_version) { - ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString()); + ::fprintf(out_fh, "%s\n", m_debugger.GetVersionString()); exiting = true; } else if (m_option_data.m_print_python_path) @@ -806,13 +786,13 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX); if (num_chars < PATH_MAX) { - ::fprintf (out_fh, "%s\n", python_path); + ::fprintf(out_fh, "%s\n", python_path); } else - ::fprintf (out_fh, "\n"); + ::fprintf(out_fh, "\n"); } else - ::fprintf (out_fh, "\n"); + ::fprintf(out_fh, "\n"); exiting = true; } else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) @@ -829,471 +809,468 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) if (argc > 0) { - for (int arg_idx=0; arg_idx 0) - ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n"); + ::fprintf(out_fh, "Warning: program arguments are ignored when attaching.\n"); } return error; } void -Driver::MainLoop () +Driver::MainLoop() { if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) { g_old_stdin_termios_is_valid = true; - atexit (reset_stdin_termios); + atexit(reset_stdin_termios); } - ::setbuf (stdin, NULL); - ::setbuf (stdout, NULL); + ::setbuf(stdin, NULL); + ::setbuf(stdout, NULL); + + m_debugger.SetErrorFileHandle(stderr, false); + m_debugger.SetOutputFileHandle(stdout, false); + m_debugger.SetInputFileHandle(stdin, true); - m_debugger.SetErrorFileHandle (stderr, false); - m_debugger.SetOutputFileHandle (stdout, false); - m_debugger.SetInputFileHandle (stdin, true); - m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); struct winsize window_size; - if (isatty (STDIN_FILENO) - && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) + if (isatty(STDIN_FILENO) && ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { if (window_size.ws_col > 0) - m_debugger.SetTerminalWidth (window_size.ws_col); + m_debugger.SetTerminalWidth(window_size.ws_col); } SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter(); - + // Before we handle any options from the command line, we parse the // .lldbinit file in the user's home directory. SBCommandReturnObject result; sb_interpreter.SourceInitFileInHomeDirectory(result); if (GetDebugMode()) { - result.PutError (m_debugger.GetErrorFileHandle()); - result.PutOutput (m_debugger.GetOutputFileHandle()); + result.PutError(m_debugger.GetErrorFileHandle()); + result.PutOutput(m_debugger.GetOutputFileHandle()); } // Now we handle options we got from the command line // First source in the commands specified to be run before the file arguments are processed. ExecuteInitialCommands(true); - + // Was there a core file specified? std::string core_file_spec(""); if (!m_option_data.m_core_file.empty()) core_file_spec.append("--core ").append(m_option_data.m_core_file); - + char command_string[PATH_MAX * 2]; const size_t num_args = m_option_data.m_args.size(); if (num_args > 0) { char arch_name[64]; - if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name))) - ::snprintf (command_string, - sizeof (command_string), - "target create --arch=%s %s \"%s\"", - arch_name, - core_file_spec.c_str(), - m_option_data.m_args[0].c_str()); + if (m_debugger.GetDefaultArchitecture(arch_name, sizeof(arch_name))) + ::snprintf(command_string, sizeof(command_string), "target create --arch=%s %s \"%s\"", arch_name, core_file_spec.c_str(), + m_option_data.m_args[0].c_str()); else - ::snprintf (command_string, - sizeof(command_string), - "target create %s \"%s\"", - core_file_spec.c_str(), - m_option_data.m_args[0].c_str()); - - m_debugger.HandleCommand (command_string); - + ::snprintf(command_string, sizeof(command_string), "target create %s \"%s\"", core_file_spec.c_str(), + m_option_data.m_args[0].c_str()); + + m_debugger.HandleCommand(command_string); + if (num_args > 1) { - m_debugger.HandleCommand ("settings clear target.run-args"); + m_debugger.HandleCommand("settings clear target.run-args"); char arg_cstr[1024]; for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx) { - ::snprintf (arg_cstr, - sizeof(arg_cstr), - "settings append target.run-args \"%s\"", - m_option_data.m_args[arg_idx].c_str()); - m_debugger.HandleCommand (arg_cstr); + ::snprintf(arg_cstr, sizeof(arg_cstr), "settings append target.run-args \"%s\"", m_option_data.m_args[arg_idx].c_str()); + m_debugger.HandleCommand(arg_cstr); } } } else if (!core_file_spec.empty()) { - ::snprintf (command_string, - sizeof(command_string), - "target create %s", - core_file_spec.c_str()); - m_debugger.HandleCommand (command_string);; + ::snprintf(command_string, sizeof(command_string), "target create %s", core_file_spec.c_str()); + m_debugger.HandleCommand(command_string); + ; } else if (!m_option_data.m_process_name.empty()) { - ::snprintf (command_string, - sizeof(command_string), - "process attach --name '%s'%s", - m_option_data.m_process_name.c_str(), - m_option_data.m_wait_for ? " --waitfor" : ""); - m_debugger.HandleCommand (command_string); + ::snprintf(command_string, sizeof(command_string), "process attach --name '%s'%s", m_option_data.m_process_name.c_str(), + m_option_data.m_wait_for ? " --waitfor" : ""); + m_debugger.HandleCommand(command_string); } else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid) { - ::snprintf (command_string, - sizeof(command_string), - "process attach --pid %" PRIu64, - m_option_data.m_process_pid); - m_debugger.HandleCommand (command_string); + ::snprintf(command_string, sizeof(command_string), "process attach --pid %" PRIu64, m_option_data.m_process_pid); + m_debugger.HandleCommand(command_string); } ExecuteInitialCommands(false); // Now that all option parsing is done, we try and parse the .lldbinit // file in the current working directory - sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result); + sb_interpreter.SourceInitFileInCurrentWorkingDirectory(result); if (GetDebugMode()) { result.PutError(m_debugger.GetErrorFileHandle()); result.PutOutput(m_debugger.GetOutputFileHandle()); } - + bool handle_events = true; bool spawn_thread = false; m_debugger.RunCommandInterpreter(handle_events, spawn_thread); - + reset_stdin_termios(); - fclose (stdin); - - SBDebugger::Destroy (m_debugger); + fclose(stdin); + + SBDebugger::Destroy(m_debugger); } void -Driver::ResizeWindow (unsigned short col) +Driver::ResizeWindow(unsigned short col) { - GetDebugger().SetTerminalWidth (col); + GetDebugger().SetTerminalWidth(col); } //++ ------------------------------------------------------------------------------------ -// Details: Setup *this driver so it works as pass through (child) driver for the MI -// driver. Called by the parent (MI driver) driver. -// This driver has setup code in two places. The original in MainLoop() and -// in int main() (when MICONFIG_COMPILE_MIDRIVER_VERSION == 0) so that code can -// remain as much near to the original code as possible. If MI driver is the main -// driver (when MICONFIG_COMPILE_MIDRIVER_VERSION == 1) then this function is -// used to set up the Driver to work with the MI driver. -// Type: Method. -// Args: vwErrMsg - (W) On failure current error discription. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Setup *this driver so it works as pass through (child) driver for the MI +// driver. Called by the parent (MI driver) driver. +// This driver has setup code in two places. The original in MainLoop() and +// in int main() (when MICONFIG_COMPILE_MIDRIVER_VERSION == 0) so that code can +// remain as much near to the original code as possible. If MI driver is the main +// driver (when MICONFIG_COMPILE_MIDRIVER_VERSION == 1) then this function is +// used to set up the Driver to work with the MI driver. +// Type: Method. +// Args: vwErrMsg - (W) On failure current error discription. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool Driver::MISetup( CMIUtilString & vwErrMsg ) +bool +Driver::MISetup(CMIUtilString &vwErrMsg) { - bool bOk = MIstatus::success; - - // Is *this driver a pass through driver to the MI driver - CMIDriverBase * pParent = GetDriversParent(); - if( pParent == nullptr ) - { - // No it is not. - // If MI is the main driver (which passes through to *this driver) then - // *this driver needs to be initialized after MI is initialize to have a valid - // pointer to the parent driver. *this is the parent's pass thru driver. - assert( pParent == nullptr ); - return MIstatus::success; // Allow success for if Driver is the main driver - } - - // MI driver may have streams it wants *this driver to use - still to be sorted - m_debugger.SetErrorFileHandle( pParent->GetStderr(), false ); // MI may redirect to its own stream - m_debugger.SetOutputFileHandle( pParent->GetStdout(), false ); // MI likely to NULL this - m_debugger.SetInputFileHandle( pParent->GetStdin(), false ); // MI could use this to feed input - + bool bOk = MIstatus::success; + + // Is *this driver a pass through driver to the MI driver + CMIDriverBase *pParent = GetDriversParent(); + if (pParent == nullptr) + { + // No it is not. + // If MI is the main driver (which passes through to *this driver) then + // *this driver needs to be initialized after MI is initialize to have a valid + // pointer to the parent driver. *this is the parent's pass thru driver. + assert(pParent == nullptr); + return MIstatus::success; // Allow success for if Driver is the main driver + } + + // MI driver may have streams it wants *this driver to use - still to be sorted + m_debugger.SetErrorFileHandle(pParent->GetStderr(), false); // MI may redirect to its own stream + m_debugger.SetOutputFileHandle(pParent->GetStdout(), false); // MI likely to NULL this + m_debugger.SetInputFileHandle(pParent->GetStdin(), false); // MI could use this to feed input + // ToDo: Do I need this? - m_debugger.SetUseExternalEditor( m_option_data.m_use_external_editor ); + m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); // ToDo: Do I need this? - struct winsize window_size; - if( isatty( STDIN_FILENO ) && ::ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) == 0 ) - { - if( window_size.ws_col > 0 ) - m_debugger.SetTerminalWidth( window_size.ws_col ); - } - - return bOk; + struct winsize window_size; + if (isatty(STDIN_FILENO) && ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) + { + if (window_size.ws_col > 0) + m_debugger.SetTerminalWidth(window_size.ws_col); + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Initialize setup *this driver ready for use. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialize setup *this driver ready for use. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool Driver::DoInitialize( void ) +bool +Driver::DoInitialize(void) { - // Do nothing - return MIstatus::success; + // Do nothing + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Unbind detach or release resources used by *this driver. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Unbind detach or release resources used by *this driver. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool Driver::DoShutdown( void ) +bool +Driver::DoShutdown(void) { - SBDebugger::Destroy( m_debugger ); - - // Is *this driver a pass through driver to the MI driver - CMIDriverBase * pParent = GetDriversParent(); - if( pParent == nullptr ) - { - // See DoInitialize(). - assert( pParent == nullptr ); - return MIstatus::success; - } - - // Put stuff here when *this driver is a pass thru driver to the MI driver - - return MIstatus::success; + SBDebugger::Destroy(m_debugger); + + // Is *this driver a pass through driver to the MI driver + CMIDriverBase *pParent = GetDriversParent(); + if (pParent == nullptr) + { + // See DoInitialize(). + assert(pParent == nullptr); + return MIstatus::success; + } + + // Put stuff here when *this driver is a pass thru driver to the MI driver + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the name for *this driver. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString & - Driver name. -// Throws: None. +// Details: Retrieve the name for *this driver. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString & - Driver name. +// Throws: None. //-- -const CMIUtilString & Driver::GetName( void ) const +const CMIUtilString & +Driver::GetName(void) const { - static CMIUtilString name( "LLDB driver" ); - return name; + static CMIUtilString name("LLDB driver"); + return name; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve *this driver's last error condition. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString - Text description. -// Throws: None. +// Details: Retrieve *this driver's last error condition. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString - Text description. +// Throws: None. //-- -CMIUtilString Driver::GetError( void ) const +CMIUtilString +Driver::GetError(void) const { - // Do nothing - to implement - return CMIUtilString(); + // Do nothing - to implement + return CMIUtilString(); } //++ ------------------------------------------------------------------------------------ -// Details: Call this function puts *this driver to work. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Call this function puts *this driver to work. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool Driver::DoMainLoop( void ) +bool +Driver::DoMainLoop(void) { - MainLoop(); + MainLoop(); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Call *this driver to resize the console window. -// Type: Overridden. -// Args: vTermWidth - (R) New window column size. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Call *this driver to resize the console window. +// Type: Overridden. +// Args: vTermWidth - (R) New window column size. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -void Driver::DoResizeWindow( const uint32_t vTermWidth ) +void +Driver::DoResizeWindow(const uint32_t vTermWidth) { - ResizeWindow( (unsigned short) vTermWidth ); + ResizeWindow((unsigned short)vTermWidth); } //++ ------------------------------------------------------------------------------------ -// Details: Call *this driver to return it's debugger. -// Type: Overridden. -// Args: None. -// Return: lldb::SBDebugger & - LLDB debugger object reference. -// Throws: None. +// Details: Call *this driver to return it's debugger. +// Type: Overridden. +// Args: None. +// Return: lldb::SBDebugger & - LLDB debugger object reference. +// Throws: None. //-- -lldb::SBDebugger & Driver::GetTheDebugger( void ) +lldb::SBDebugger & +Driver::GetTheDebugger(void) { - return GetDebugger(); + return GetDebugger(); } //++ ------------------------------------------------------------------------------------ -// Details: Proxy function to allow the driver implementation to validate executable -// command line arguments. -// Type: Overrideable. -// Args: argc - (R) An integer that contains the count of arguments that follow in -// argv. The argc parameter is always greater than or equal to 1. -// argv - (R) An array of null-terminated strings representing command-line -// arguments entered by the user of the program. By convention, -// argv[0] is the command with which the program is invoked. -// vpStdOut - (R) Pointer to a standard output stream. -// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s), -// version information only. -// False = Continue to work, start debugger i.e. Command -// interpreter. -// Return: lldb::SBError - LLDB current error status. -// Throws: None. +// Details: Proxy function to allow the driver implementation to validate executable +// command line arguments. +// Type: Overrideable. +// Args: argc - (R) An integer that contains the count of arguments that follow in +// argv. The argc parameter is always greater than or equal to 1. +// argv - (R) An array of null-terminated strings representing command-line +// arguments entered by the user of the program. By convention, +// argv[0] is the command with which the program is invoked. +// vpStdOut - (R) Pointer to a standard output stream. +// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s), +// version information only. +// False = Continue to work, start debugger i.e. Command +// interpreter. +// Return: lldb::SBError - LLDB current error status. +// Throws: None. //-- -lldb::SBError Driver::DoParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting ) +lldb::SBError +Driver::DoParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting) { - return ParseArgs( argc, argv, vpStdOut, vwbExiting ); + return ParseArgs(argc, argv, vpStdOut, vwbExiting); } - + //++ ------------------------------------------------------------------------------------ -// Details: A client can ask if *this driver is GDB/MI compatible. -// Type: Overridden. -// Args: None. -// Return: True - GBD/MI compatible LLDB front end. -// False - Not GBD/MI compatible LLDB front end. -// Throws: None. +// Details: A client can ask if *this driver is GDB/MI compatible. +// Type: Overridden. +// Args: None. +// Return: True - GBD/MI compatible LLDB front end. +// False - Not GBD/MI compatible LLDB front end. +// Throws: None. //-- -bool Driver::GetDriverIsGDBMICompatibleDriver( void ) const +bool +Driver::GetDriverIsGDBMICompatibleDriver(void) const { - return false; + return false; } //++ ------------------------------------------------------------------------------------ -// Details: This function allows *this driver to call on another driver to perform work -// should this driver not be able to handle the client data input. -// SetDriverToFallThruTo() specifies the fall through to driver. -// Check the error message if the function returns a failure. -// Type: Overridden. -// Args: vCmd - (R) Command instruction to interpret. -// vwErrMsg - (W) Error description on command failing. -// Return: MIstatus::success - Command succeeded. -// MIstatus::failure - Command failed. -// Throws: None. +// Details: This function allows *this driver to call on another driver to perform work +// should this driver not be able to handle the client data input. +// SetDriverToFallThruTo() specifies the fall through to driver. +// Check the error message if the function returns a failure. +// Type: Overridden. +// Args: vCmd - (R) Command instruction to interpret. +// vwErrMsg - (W) Error description on command failing. +// Return: MIstatus::success - Command succeeded. +// MIstatus::failure - Command failed. +// Throws: None. //-- -bool Driver::DoFallThruToAnotherDriver( const CMIUtilString & vCmd, CMIUtilString & vwErrMsg ) +bool +Driver::DoFallThruToAnotherDriver(const CMIUtilString &vCmd, CMIUtilString &vwErrMsg) { - bool bOk = MIstatus::success; - vwErrMsg.empty(); - - // ToDo: Implement do work on other driver after this driver said "Give up you try" - // This may nto be required if the feature to 'fall through' is not required - SBCommandReturnObject returnObj = lldb::SBCommandReturnObject(); - SBCommandInterpreter cmdIntrp = m_debugger.GetCommandInterpreter(); - const lldb::ReturnStatus cmdResult = cmdIntrp.HandleCommand( vCmd.c_str(), returnObj ); MIunused( cmdResult ); - if( returnObj.Succeeded() == false ) - { - bOk = MIstatus::failure; - vwErrMsg = returnObj.GetError(); - } - - return bOk; + bool bOk = MIstatus::success; + vwErrMsg.empty(); + + // ToDo: Implement do work on other driver after this driver said "Give up you try" + // This may nto be required if the feature to 'fall through' is not required + SBCommandReturnObject returnObj = lldb::SBCommandReturnObject(); + SBCommandInterpreter cmdIntrp = m_debugger.GetCommandInterpreter(); + const lldb::ReturnStatus cmdResult = cmdIntrp.HandleCommand(vCmd.c_str(), returnObj); + MIunused(cmdResult); + if (returnObj.Succeeded() == false) + { + bOk = MIstatus::failure; + vwErrMsg = returnObj.GetError(); + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: This function allows *this driver to call functionality on the parent driver -// ask for information for example. -// Type: Overridden. -// Args: vrOtherDriver - (R) Reference to another driver object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: This function allows *this driver to call functionality on the parent driver +// ask for information for example. +// Type: Overridden. +// Args: vrOtherDriver - (R) Reference to another driver object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool Driver::SetDriverParent( const CMIDriverBase & vrOtherDriver ) +bool +Driver::SetDriverParent(const CMIDriverBase &vrOtherDriver) { - m_pDriverParent = const_cast< CMIDriverBase * >( &vrOtherDriver ); - - return MIstatus::success; + m_pDriverParent = const_cast(&vrOtherDriver); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Set a unique ID for *this driver. It cannot be empty. -// Type: Overridden. -// Args: vId - (R) Text description. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Set a unique ID for *this driver. It cannot be empty. +// Type: Overridden. +// Args: vId - (R) Text description. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool Driver::SetId( const CMIUtilString & vId ) +bool +Driver::SetId(const CMIUtilString &vId) { - if( vId.empty() ) - { - // Invalid to have it empty - return MIstatus::failure; - } - - m_strDriverId = vId; - return MIstatus::success; + if (vId.empty()) + { + // Invalid to have it empty + return MIstatus::failure; + } + + m_strDriverId = vId; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Get the unique ID for *this driver. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString & - Text description. -// Throws: None. +// Details: Get the unique ID for *this driver. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString & - Text description. +// Throws: None. //-- -const CMIUtilString & Driver::GetId( void ) const +const CMIUtilString & +Driver::GetId(void) const { - return m_strDriverId; + return m_strDriverId; } //++ ------------------------------------------------------------------------------------ -// Details: Create *this driver. Function contains functionality that needs to be called -// prior to constructing the *this driver. -// Type: Static method. -// Args: None. -// Return: Driver * - Ptr to the LLDB driver object. -// Throws: None. +// Details: Create *this driver. Function contains functionality that needs to be called +// prior to constructing the *this driver. +// Type: Static method. +// Args: None. +// Return: Driver * - Ptr to the LLDB driver object. +// Throws: None. //-- -Driver * Driver::CreateSelf( void ) +Driver * +Driver::CreateSelf(void) { - lldb::SBDebugger::Initialize(); - - Driver * pDriver = new Driver; - return pDriver; + lldb::SBDebugger::Initialize(); + + Driver *pDriver = new Driver; + return pDriver; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the name for *this driver. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString - Driver name. -// Throws: None. +// Details: Retrieve the name for *this driver. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString - Driver name. +// Throws: None. //-- -const CMIUtilString & Driver::GetDriverName( void ) const +const CMIUtilString & +Driver::GetDriverName(void) const { - return GetName(); + return GetName(); } //++ ------------------------------------------------------------------------------------ -// Details: Get the unique ID for *this driver. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString & - Text description. -// Throws: None. +// Details: Get the unique ID for *this driver. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString & - Text description. +// Throws: None. //-- -const CMIUtilString & Driver::GetDriverId( void ) const +const CMIUtilString & +Driver::GetDriverId(void) const { - return GetId(); + return GetId(); } #endif // MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER - diff --git a/tools/lldb-mi/Driver.h b/tools/lldb-mi/Driver.h index 39577c49bf05..41fc21da407e 100644 --- a/tools/lldb-mi/Driver.h +++ b/tools/lldb-mi/Driver.h @@ -36,86 +36,75 @@ class IOChannel; class Driver : public lldb::SBBroadcaster, public CMIDriverBase, public CMIDriverMgr::IDriver { -// MI required code: -// Static: -public: - static Driver * CreateSelf( void ); - -// Methods: -public: - bool MISetup( CMIUtilString & vwErrMsg ); - -// Overridden: -public: - // From CMIDriverMgr::IDriver - virtual bool DoInitialize( void ); - virtual bool DoShutdown( void ); - virtual bool DoMainLoop( void ); - virtual void DoResizeWindow( const uint32_t vWindowSizeWsCol ); - virtual lldb::SBError DoParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting ); - virtual CMIUtilString GetError( void ) const; - virtual const CMIUtilString & GetName( void ) const; - virtual lldb::SBDebugger & GetTheDebugger( void ); - virtual bool GetDriverIsGDBMICompatibleDriver( void ) const; - virtual bool SetId( const CMIUtilString & vID ); - virtual const CMIUtilString & GetId( void ) const; - // From CMIDriverBase - virtual bool DoFallThruToAnotherDriver( const CMIUtilString & vCmd, CMIUtilString & vwErrMsg ); - virtual bool SetDriverParent( const CMIDriverBase & vrOtherDriver ); - virtual const CMIUtilString & GetDriverName( void ) const; - virtual const CMIUtilString & GetDriverId( void ) const; - -// Original code: -public: - Driver (); - - virtual - ~Driver (); - - void - MainLoop (); - - lldb::SBError - ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &do_exit); - - const char * - GetFilename() const; - - const char * - GetCrashLogFilename() const; - - const char * - GetArchName() const; - - lldb::ScriptLanguage - GetScriptLanguage() const; - - void - ExecuteInitialCommands (bool before_file); - - bool - GetDebugMode() const; + // MI required code: + // Static: + public: + static Driver *CreateSelf(void); + + // Methods: + public: + bool MISetup(CMIUtilString &vwErrMsg); + + // Overridden: + public: + // From CMIDriverMgr::IDriver + virtual bool DoInitialize(void); + virtual bool DoShutdown(void); + virtual bool DoMainLoop(void); + virtual void DoResizeWindow(const uint32_t vWindowSizeWsCol); + virtual lldb::SBError DoParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting); + virtual CMIUtilString GetError(void) const; + virtual const CMIUtilString &GetName(void) const; + virtual lldb::SBDebugger &GetTheDebugger(void); + virtual bool GetDriverIsGDBMICompatibleDriver(void) const; + virtual bool SetId(const CMIUtilString &vID); + virtual const CMIUtilString &GetId(void) const; + // From CMIDriverBase + virtual bool DoFallThruToAnotherDriver(const CMIUtilString &vCmd, CMIUtilString &vwErrMsg); + virtual bool SetDriverParent(const CMIDriverBase &vrOtherDriver); + virtual const CMIUtilString &GetDriverName(void) const; + virtual const CMIUtilString &GetDriverId(void) const; + + // Original code: + public: + Driver(); + + virtual ~Driver(); + + void MainLoop(); + + lldb::SBError ParseArgs(int argc, const char *argv[], FILE *out_fh, bool &do_exit); + + const char *GetFilename() const; + + const char *GetCrashLogFilename() const; + + const char *GetArchName() const; + + lldb::ScriptLanguage GetScriptLanguage() const; + + void ExecuteInitialCommands(bool before_file); + + bool GetDebugMode() const; class OptionData { - public: - OptionData (); - ~OptionData (); + public: + OptionData(); + ~OptionData(); - void - Clear(); + void Clear(); - void - AddInitialCommand (const char *command, bool before_file, bool is_file, lldb::SBError &error); - - //static OptionDefinition m_cmd_option_table[]; + void AddInitialCommand(const char *command, bool before_file, bool is_file, lldb::SBError &error); + + // static OptionDefinition m_cmd_option_table[]; std::vector m_args; lldb::ScriptLanguage m_script_lang; std::string m_core_file; std::string m_crash_log; - std::vector > m_initial_commands; - std::vector > m_after_file_commands; + std::vector> m_initial_commands; + std::vector> m_after_file_commands; bool m_debug_mode; bool m_source_quietly; bool m_print_version; @@ -124,39 +113,31 @@ public: bool m_wait_for; std::string m_process_name; lldb::pid_t m_process_pid; - bool m_use_external_editor; // FIXME: When we have set/show variables we can remove this from here. + bool m_use_external_editor; // FIXME: When we have set/show variables we can remove this from here. typedef std::set OptionSet; OptionSet m_seen_options; }; - - static lldb::SBError - SetOptionValue (int option_idx, - const char *option_arg, - Driver::OptionData &data); - + static lldb::SBError SetOptionValue(int option_idx, const char *option_arg, Driver::OptionData &data); lldb::SBDebugger & GetDebugger() { return m_debugger; } - - void - ResizeWindow (unsigned short col); -private: + void ResizeWindow(unsigned short col); + + private: lldb::SBDebugger m_debugger; OptionData m_option_data; - void - ResetOptionValues (); + void ResetOptionValues(); - void - ReadyForCommand (); + void ReadyForCommand(); }; -extern Driver * g_driver; +extern Driver *g_driver; #endif // lldb_Driver_h_ diff --git a/tools/lldb-mi/MICmdArgContext.cpp b/tools/lldb-mi/MICmdArgContext.cpp index b6efa9660c3b..217913cff175 100644 --- a/tools/lldb-mi/MICmdArgContext.cpp +++ b/tools/lldb-mi/MICmdArgContext.cpp @@ -8,248 +8,254 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnArgContext.cpp +// File: MICmnArgContext.cpp // -// Overview: CMICmdArgContext implementation. +// Overview: CMICmdArgContext implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: #include "MICmdArgContext.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgContext constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgContext constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgContext::CMICmdArgContext( void ) -: m_constCharSpace( ' ' ) -, m_constStrSpace( " " ) +CMICmdArgContext::CMICmdArgContext(void) + : m_constCharSpace(' ') + , m_constStrSpace(" ") { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgContext constructor. -// Type: Method. -// Args: vrCmdLineArgsRaw - (R) The text description of the arguments options. -// Return: None. -// Throws: None. +// Details: CMICmdArgContext constructor. +// Type: Method. +// Args: vrCmdLineArgsRaw - (R) The text description of the arguments options. +// Return: None. +// Throws: None. //-- -CMICmdArgContext::CMICmdArgContext( const CMIUtilString & vrCmdLineArgsRaw ) -: m_strCmdArgsAndOptions( vrCmdLineArgsRaw ) -, m_constCharSpace( ' ' ) -, m_constStrSpace( " " ) +CMICmdArgContext::CMICmdArgContext(const CMIUtilString &vrCmdLineArgsRaw) + : m_strCmdArgsAndOptions(vrCmdLineArgsRaw) + , m_constCharSpace(' ') + , m_constStrSpace(" ") { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgContext destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgContext destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgContext::~CMICmdArgContext( void ) +CMICmdArgContext::~CMICmdArgContext(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the remainder of the command's argument options left to parse. -// Type: Method. -// Args: None. -// Return: CMIUtilString & - Argument options text. -// Throws: None. +// Details: Retrieve the remainder of the command's argument options left to parse. +// Type: Method. +// Args: None. +// Return: CMIUtilString & - Argument options text. +// Throws: None. //-- -const CMIUtilString & CMICmdArgContext::GetArgsLeftToParse( void ) const +const CMIUtilString & +CMICmdArgContext::GetArgsLeftToParse(void) const { - return m_strCmdArgsAndOptions; + return m_strCmdArgsAndOptions; } //++ ------------------------------------------------------------------------------------ -// Details: Ask if this arguments string has any arguments. -// Type: Method. -// Args: None. -// Return: bool - True = Has one or more arguments present, false = no arguments. -// Throws: None. +// Details: Ask if this arguments string has any arguments. +// Type: Method. +// Args: None. +// Return: bool - True = Has one or more arguments present, false = no arguments. +// Throws: None. //-- -bool CMICmdArgContext::IsEmpty( void ) const +bool +CMICmdArgContext::IsEmpty(void) const { - return m_strCmdArgsAndOptions.empty(); + return m_strCmdArgsAndOptions.empty(); } - + //++ ------------------------------------------------------------------------------------ -// Details: Remove the argument from the options text and any space after the argument -// if applicable. -// Type: Method. -// Args: vArg - (R) The name of the argument. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Remove the argument from the options text and any space after the argument +// if applicable. +// Type: Method. +// Args: vArg - (R) The name of the argument. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgContext::RemoveArg( const CMIUtilString & vArg ) +bool +CMICmdArgContext::RemoveArg(const CMIUtilString &vArg) { - if( vArg.empty() ) - return MIstatus::success; - - const MIuint nLen = vArg.length(); - const MIuint nLenCntxt = m_strCmdArgsAndOptions.length(); - if( nLen > nLenCntxt ) - return MIstatus::failure; - - MIuint nExtraSpace = 0; - MIint nPos = m_strCmdArgsAndOptions.find( vArg ); - while( 1 ) - { - if( nPos == (MIint) std::string::npos ) - return MIstatus::success; - - bool bPass1 = false; - if( nPos != 0 ) - { - if( m_strCmdArgsAndOptions[ nPos - 1 ] == m_constCharSpace ) - bPass1 = true; - } - else - bPass1 = true; - - const MIuint nEnd = nPos + nLen; - - if( bPass1 ) - { - bool bPass2 = false; - if( nEnd < nLenCntxt ) - { - if( m_strCmdArgsAndOptions[ nEnd ] == m_constCharSpace ) - { - bPass2 = true; - nExtraSpace = 1; - } - } - else - bPass2 = true; - - if( bPass2 ) - break; - } - - nPos = m_strCmdArgsAndOptions.find( vArg, nEnd ); - } - - const MIuint nPosEnd = nLen + nExtraSpace; - m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.replace( nPos, nPosEnd, "" ).c_str(); - m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.Trim(); - - return MIstatus::success; + if (vArg.empty()) + return MIstatus::success; + + const MIuint nLen = vArg.length(); + const MIuint nLenCntxt = m_strCmdArgsAndOptions.length(); + if (nLen > nLenCntxt) + return MIstatus::failure; + + MIuint nExtraSpace = 0; + MIint nPos = m_strCmdArgsAndOptions.find(vArg); + while (1) + { + if (nPos == (MIint)std::string::npos) + return MIstatus::success; + + bool bPass1 = false; + if (nPos != 0) + { + if (m_strCmdArgsAndOptions[nPos - 1] == m_constCharSpace) + bPass1 = true; + } + else + bPass1 = true; + + const MIuint nEnd = nPos + nLen; + + if (bPass1) + { + bool bPass2 = false; + if (nEnd < nLenCntxt) + { + if (m_strCmdArgsAndOptions[nEnd] == m_constCharSpace) + { + bPass2 = true; + nExtraSpace = 1; + } + } + else + bPass2 = true; + + if (bPass2) + break; + } + + nPos = m_strCmdArgsAndOptions.find(vArg, nEnd); + } + + const MIuint nPosEnd = nLen + nExtraSpace; + m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.replace(nPos, nPosEnd, "").c_str(); + m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.Trim(); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Remove the argument at the Nth word position along in the context string. -// Any space after the argument is removed if applicable. A search is not -// performed as there may be more than one vArg with the same 'name' in the -// context string. -// Type: Method. -// Args: vArg - (R) The name of the argument. -// nArgIndex - (R) The word count position to which to remove the vArg word. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Remove the argument at the Nth word position along in the context string. +// Any space after the argument is removed if applicable. A search is not +// performed as there may be more than one vArg with the same 'name' in the +// context string. +// Type: Method. +// Args: vArg - (R) The name of the argument. +// nArgIndex - (R) The word count position to which to remove the vArg word. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgContext::RemoveArgAtPos( const CMIUtilString & vArg, const MIuint nArgIndex ) +bool +CMICmdArgContext::RemoveArgAtPos(const CMIUtilString &vArg, const MIuint nArgIndex) { - MIuint nWordIndex = 0; - CMIUtilString strBuildContextUp; - const CMIUtilString::VecString_t vecWords( GetArgs() ); - const bool bSpaceRequired( GetNumberArgsPresent() > 2 ); - - CMIUtilString::VecString_t::const_iterator it = vecWords.begin(); - const CMIUtilString::VecString_t::const_iterator itEnd = vecWords.end(); - while( it != itEnd ) - { - const CMIUtilString & rWord( *it ); - if( nWordIndex++ != nArgIndex ) - { - // Single words - strBuildContextUp += rWord; - if( bSpaceRequired ) - strBuildContextUp += m_constStrSpace; - } - else - { - // If quoted loose quoted text - if( ++it != itEnd ) - { - CMIUtilString words = rWord; - while( vArg != words ) - { - if( bSpaceRequired ) - words += m_constStrSpace; - words += *it; - if( ++it == itEnd ) - break; - } - if( it != itEnd ) - --it; - } - } - - // Next - if( it != itEnd ) - ++it; - } - - m_strCmdArgsAndOptions = strBuildContextUp; - m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.Trim(); - - return MIstatus::success; + MIuint nWordIndex = 0; + CMIUtilString strBuildContextUp; + const CMIUtilString::VecString_t vecWords(GetArgs()); + const bool bSpaceRequired(GetNumberArgsPresent() > 2); + + CMIUtilString::VecString_t::const_iterator it = vecWords.begin(); + const CMIUtilString::VecString_t::const_iterator itEnd = vecWords.end(); + while (it != itEnd) + { + const CMIUtilString &rWord(*it); + if (nWordIndex++ != nArgIndex) + { + // Single words + strBuildContextUp += rWord; + if (bSpaceRequired) + strBuildContextUp += m_constStrSpace; + } + else + { + // If quoted loose quoted text + if (++it != itEnd) + { + CMIUtilString words = rWord; + while (vArg != words) + { + if (bSpaceRequired) + words += m_constStrSpace; + words += *it; + if (++it == itEnd) + break; + } + if (it != itEnd) + --it; + } + } + + // Next + if (it != itEnd) + ++it; + } + + m_strCmdArgsAndOptions = strBuildContextUp; + m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.Trim(); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve number of arguments or options present in the command's option text. -// Type: Method. -// Args: None. -// Return: MIuint - 0 to n arguments present. -// Throws: None. +// Details: Retrieve number of arguments or options present in the command's option text. +// Type: Method. +// Args: None. +// Return: MIuint - 0 to n arguments present. +// Throws: None. //-- -MIuint CMICmdArgContext::GetNumberArgsPresent( void ) const +MIuint +CMICmdArgContext::GetNumberArgsPresent(void) const { - CMIUtilString::VecString_t vecOptions; - return m_strCmdArgsAndOptions.SplitConsiderQuotes( m_constStrSpace, vecOptions ); + CMIUtilString::VecString_t vecOptions; + return m_strCmdArgsAndOptions.SplitConsiderQuotes(m_constStrSpace, vecOptions); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve all the arguments or options remaining in *this context. -// Type: Method. -// Args: None. -// Return: MIUtilString::VecString_t - List of args remaining. -// Throws: None. +// Details: Retrieve all the arguments or options remaining in *this context. +// Type: Method. +// Args: None. +// Return: MIUtilString::VecString_t - List of args remaining. +// Throws: None. //-- -CMIUtilString::VecString_t CMICmdArgContext::GetArgs( void ) const +CMIUtilString::VecString_t +CMICmdArgContext::GetArgs(void) const { - CMIUtilString::VecString_t vecOptions; - m_strCmdArgsAndOptions.SplitConsiderQuotes( m_constStrSpace, vecOptions ); - return vecOptions; + CMIUtilString::VecString_t vecOptions; + m_strCmdArgsAndOptions.SplitConsiderQuotes(m_constStrSpace, vecOptions); + return vecOptions; } - + //++ ------------------------------------------------------------------------------------ -// Details: Copy assignment operator. -// Type: Method. -// Args: vOther - (R) The variable to copy from. -// Return: CMIUtilString & - this object. -// Throws: None. +// Details: Copy assignment operator. +// Type: Method. +// Args: vOther - (R) The variable to copy from. +// Return: CMIUtilString & - this object. +// Throws: None. //-- -CMICmdArgContext & CMICmdArgContext::operator= ( const CMICmdArgContext & vOther ) +CMICmdArgContext &CMICmdArgContext::operator=(const CMICmdArgContext &vOther) { - if( this != &vOther ) - { - m_strCmdArgsAndOptions = vOther.m_strCmdArgsAndOptions; - } - - return *this; -} \ No newline at end of file + if (this != &vOther) + { + m_strCmdArgsAndOptions = vOther.m_strCmdArgsAndOptions; + } + + return *this; +} diff --git a/tools/lldb-mi/MICmdArgContext.h b/tools/lldb-mi/MICmdArgContext.h index 699bac13e014..7178373ce380 100644 --- a/tools/lldb-mi/MICmdArgContext.h +++ b/tools/lldb-mi/MICmdArgContext.h @@ -8,54 +8,54 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgContext.h +// File: MICmdArgContext.h // -// Overview: CMICmdArgContext interface. +// Overview: CMICmdArgContext interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once // In-house headers: -#include "MIUtilString.h" +#include "MIUtilString.h" //++ ============================================================================ -// Details: MI common code class. Command arguments and options string. Holds -// the context string. -// Based on the Interpreter pattern. -// Gotchas: None. -// Authors: Illya Rudkin 14/04/2014. -// Changes: None. +// Details: MI common code class. Command arguments and options string. Holds +// the context string. +// Based on the Interpreter pattern. +// Gotchas: None. +// Authors: Illya Rudkin 14/04/2014. +// Changes: None. //-- class CMICmdArgContext { -// Methods: -public: - /* ctor */ CMICmdArgContext( void ); - /* ctor */ CMICmdArgContext( const CMIUtilString & vrCmdLineArgsRaw ); - // - const CMIUtilString & GetArgsLeftToParse( void ) const; - MIuint GetNumberArgsPresent( void ) const; - CMIUtilString::VecString_t GetArgs( void ) const; - bool IsEmpty( void ) const; - bool RemoveArg( const CMIUtilString & vArg ); - bool RemoveArgAtPos( const CMIUtilString & vArg, const MIuint nArgIndex ); - // - CMICmdArgContext & operator= ( const CMICmdArgContext & vOther ); - -// Overridden: -public: - // From CMIUtilString - /* dtor */ virtual ~CMICmdArgContext( void ); + // Methods: + public: + /* ctor */ CMICmdArgContext(void); + /* ctor */ CMICmdArgContext(const CMIUtilString &vrCmdLineArgsRaw); + // + const CMIUtilString &GetArgsLeftToParse(void) const; + MIuint GetNumberArgsPresent(void) const; + CMIUtilString::VecString_t GetArgs(void) const; + bool IsEmpty(void) const; + bool RemoveArg(const CMIUtilString &vArg); + bool RemoveArgAtPos(const CMIUtilString &vArg, const MIuint nArgIndex); + // + CMICmdArgContext &operator=(const CMICmdArgContext &vOther); -// Attributes: -private: - CMIUtilString m_strCmdArgsAndOptions; - const MIchar m_constCharSpace; - const CMIUtilString m_constStrSpace; + // Overridden: + public: + // From CMIUtilString + /* dtor */ virtual ~CMICmdArgContext(void); + + // Attributes: + private: + CMIUtilString m_strCmdArgsAndOptions; + const MIchar m_constCharSpace; + const CMIUtilString m_constStrSpace; }; diff --git a/tools/lldb-mi/MICmdArgSet.cpp b/tools/lldb-mi/MICmdArgSet.cpp index b0bee357cd6b..290f9eef8a9d 100644 --- a/tools/lldb-mi/MICmdArgSet.cpp +++ b/tools/lldb-mi/MICmdArgSet.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgSet.cpp +// File: MICmdArgSet.cpp // -// Overview: CMICmdArgSet implementation. +// Overview: CMICmdArgSet implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -26,395 +26,409 @@ #include "MICmnLog.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgSet constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgSet constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgSet::CMICmdArgSet( void ) -: m_bIsArgsPresentButNotHandledByCmd( false ) -, m_constStrCommaSpc( ", " ) +CMICmdArgSet::CMICmdArgSet(void) + : m_bIsArgsPresentButNotHandledByCmd(false) + , m_constStrCommaSpc(", ") { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgSet destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgSet destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgSet::~CMICmdArgSet( void ) +CMICmdArgSet::~CMICmdArgSet(void) { - // Tidy up - Destroy(); + // Tidy up + Destroy(); } //++ ------------------------------------------------------------------------------------ -// Details: Release resources used by *this container object. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: Release resources used by *this container object. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMICmdArgSet::Destroy( void ) +void +CMICmdArgSet::Destroy(void) { - // Delete command argument objects - if( !m_setCmdArgs.empty() ) - { - SetCmdArgs_t::iterator it = m_setCmdArgs.begin(); - while( it != m_setCmdArgs.end() ) - { - CMICmdArgValBase * pArg( *it ); - delete pArg; - - // Next - ++it; - } - m_setCmdArgs.clear(); - } - - m_setCmdArgsThatNotValid.clear(); - m_setCmdArgsThatAreMissing.clear(); - m_setCmdArgsNotHandledByCmd.clear(); - m_setCmdArgsMissingInfo.clear(); - m_bIsArgsPresentButNotHandledByCmd = false; + // Delete command argument objects + if (!m_setCmdArgs.empty()) + { + SetCmdArgs_t::iterator it = m_setCmdArgs.begin(); + while (it != m_setCmdArgs.end()) + { + CMICmdArgValBase *pArg(*it); + delete pArg; + + // Next + ++it; + } + m_setCmdArgs.clear(); + } + + m_setCmdArgsThatNotValid.clear(); + m_setCmdArgsThatAreMissing.clear(); + m_setCmdArgsNotHandledByCmd.clear(); + m_setCmdArgsMissingInfo.clear(); + m_bIsArgsPresentButNotHandledByCmd = false; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the state flag indicating that the command set up ready to parse -// command arguments or options found that one or more arguments was indeed -// present but not handled. This is given as a warning in the MI log file. -// Type: Method. -// Args: None. -// Return: bool - True = one or more args not handled, false = all args handled -// Throws: None. +// Details: Retrieve the state flag indicating that the command set up ready to parse +// command arguments or options found that one or more arguments was indeed +// present but not handled. This is given as a warning in the MI log file. +// Type: Method. +// Args: None. +// Return: bool - True = one or more args not handled, false = all args handled +// Throws: None. //-- -bool CMICmdArgSet::IsArgsPresentButNotHandledByCmd( void ) const +bool +CMICmdArgSet::IsArgsPresentButNotHandledByCmd(void) const { - return m_bIsArgsPresentButNotHandledByCmd; + return m_bIsArgsPresentButNotHandledByCmd; } - + //++ ------------------------------------------------------------------------------------ -// Details: Add the list of command's arguments to parse and validate another one. -// Type: Method. -// Args: vArg - (R) A command argument object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Add the list of command's arguments to parse and validate another one. +// Type: Method. +// Args: vArg - (R) A command argument object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgSet::Add( const CMICmdArgValBase & vArg ) +bool +CMICmdArgSet::Add(const CMICmdArgValBase &vArg) { - CMICmdArgValBase * pArg = const_cast< CMICmdArgValBase * >( &vArg ); - m_setCmdArgs.push_back( pArg ); + CMICmdArgValBase *pArg = const_cast(&vArg); + m_setCmdArgs.push_back(pArg); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: After validating an options line of text (the context) and there is a failure, -// it is likely a mandatory command argument that is required is missing. This -// function returns the argument that should be present. -// Type: Method. -// Args: None. -// Return: SetCmdArgs_t & - Set of argument objects. -// Throws: None. +// Details: After validating an options line of text (the context) and there is a failure, +// it is likely a mandatory command argument that is required is missing. This +// function returns the argument that should be present. +// Type: Method. +// Args: None. +// Return: SetCmdArgs_t & - Set of argument objects. +// Throws: None. //-- -const CMICmdArgSet::SetCmdArgs_t & CMICmdArgSet::GetArgsThatAreMissing( void ) const +const CMICmdArgSet::SetCmdArgs_t & +CMICmdArgSet::GetArgsThatAreMissing(void) const { - return m_setCmdArgsThatAreMissing; + return m_setCmdArgsThatAreMissing; } //++ ------------------------------------------------------------------------------------ -// Details: After validating an options line of text (the context) and there is a failure, -// it may be because one or more arguments were unable to extract a value. This -// function returns the argument that were found to be invalid. -// Type: Method. -// Args: None. -// Return: SetCmdArgs_t & - Set of argument objects. -// Throws: None. +// Details: After validating an options line of text (the context) and there is a failure, +// it may be because one or more arguments were unable to extract a value. This +// function returns the argument that were found to be invalid. +// Type: Method. +// Args: None. +// Return: SetCmdArgs_t & - Set of argument objects. +// Throws: None. //-- -const CMICmdArgSet::SetCmdArgs_t & CMICmdArgSet::GetArgsThatInvalid( void ) const +const CMICmdArgSet::SetCmdArgs_t & +CMICmdArgSet::GetArgsThatInvalid(void) const { - return m_setCmdArgsThatNotValid; -} + return m_setCmdArgsThatNotValid; +} //++ ------------------------------------------------------------------------------------ -// Details: The list of argument or option (objects) that were specified by the command -// and so recognised when parsed but were not handled. Ideally the command -// should handle all arguments and options presented to it. The command sends -// warning to the MI log file to say that these options were not handled. -// Used as one way to determine option that maybe should really be implemented -// and not just ignored. -// Type: Method. -// Args: None. -// Return: SetCmdArgs_t & - Set of argument objects. -// Throws: None. +// Details: The list of argument or option (objects) that were specified by the command +// and so recognised when parsed but were not handled. Ideally the command +// should handle all arguments and options presented to it. The command sends +// warning to the MI log file to say that these options were not handled. +// Used as one way to determine option that maybe should really be implemented +// and not just ignored. +// Type: Method. +// Args: None. +// Return: SetCmdArgs_t & - Set of argument objects. +// Throws: None. //-- -const CMICmdArgSet::SetCmdArgs_t & CMICmdArgSet::GetArgsNotHandledByCmd( void ) const +const CMICmdArgSet::SetCmdArgs_t & +CMICmdArgSet::GetArgsNotHandledByCmd(void) const { - return m_setCmdArgsNotHandledByCmd; + return m_setCmdArgsNotHandledByCmd; } //++ ------------------------------------------------------------------------------------ -// Details: Given a set of command argument objects parse the context option string to -// find those argument and retrieve their value. If the function fails call -// GetArgsThatAreMissing() to see which commands that were mandatory were -// missing or failed to parse. -// Type: Method. -// Args: vStrMiCmd - (R) Command's name. -// vCmdArgsText - (RW) A command's options or argument. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Given a set of command argument objects parse the context option string to +// find those argument and retrieve their value. If the function fails call +// GetArgsThatAreMissing() to see which commands that were mandatory were +// missing or failed to parse. +// Type: Method. +// Args: vStrMiCmd - (R) Command's name. +// vCmdArgsText - (RW) A command's options or argument. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgSet::Validate( const CMIUtilString & vStrMiCmd, CMICmdArgContext & vwCmdArgsText ) +bool +CMICmdArgSet::Validate(const CMIUtilString &vStrMiCmd, CMICmdArgContext &vwCmdArgsText) { - m_cmdArgContext = vwCmdArgsText; - - // Iterate all the arguments or options required by a command - const MIuint nArgs = vwCmdArgsText.GetNumberArgsPresent(); - MIuint nArgsMandatoryCnt = 0; - SetCmdArgs_t::const_iterator it = m_setCmdArgs.begin(); - while( it != m_setCmdArgs.end() ) - { - const CMICmdArgValBase * pArg( *it ); - const CMIUtilString & rArgName( pArg->GetName() ); MIunused( rArgName ); - if( pArg->GetIsMandatory() ) - nArgsMandatoryCnt++; - if( !const_cast< CMICmdArgValBase * >( pArg )->Validate( vwCmdArgsText ) ) - { - if( pArg->GetIsMandatory() && !pArg->GetFound() ) - m_setCmdArgsThatAreMissing.push_back( const_cast< CMICmdArgValBase * >( pArg ) ); - else if( pArg->GetFound() ) - { - if( pArg->GetIsMissingOptions() ) - m_setCmdArgsMissingInfo.push_back( const_cast< CMICmdArgValBase * >( pArg ) ); - else if( !pArg->GetValid() ) - m_setCmdArgsThatNotValid.push_back( const_cast< CMICmdArgValBase * >( pArg ) ); - } - } - if( pArg->GetFound() && !pArg->GetIsHandledByCmd() ) - { - m_bIsArgsPresentButNotHandledByCmd = true; - m_setCmdArgsNotHandledByCmd.push_back( const_cast< CMICmdArgValBase * >( pArg ) ); - } - - // Next - ++it; - } - - // Check that one or more argument objects have any issues to report... - - if( nArgs < nArgsMandatoryCnt ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_N_OPTIONS_REQUIRED ), nArgsMandatoryCnt ) ); - return MIstatus::failure; - } - - if( IsArgsPresentButNotHandledByCmd() ) - WarningArgsNotHandledbyCmdLogFile( vStrMiCmd ); - - return ValidationFormErrorMessages( vwCmdArgsText ); + m_cmdArgContext = vwCmdArgsText; + + // Iterate all the arguments or options required by a command + const MIuint nArgs = vwCmdArgsText.GetNumberArgsPresent(); + MIuint nArgsMandatoryCnt = 0; + SetCmdArgs_t::const_iterator it = m_setCmdArgs.begin(); + while (it != m_setCmdArgs.end()) + { + const CMICmdArgValBase *pArg(*it); + const CMIUtilString &rArgName(pArg->GetName()); + MIunused(rArgName); + if (pArg->GetIsMandatory()) + nArgsMandatoryCnt++; + if (!const_cast(pArg)->Validate(vwCmdArgsText)) + { + if (pArg->GetIsMandatory() && !pArg->GetFound()) + m_setCmdArgsThatAreMissing.push_back(const_cast(pArg)); + else if (pArg->GetFound()) + { + if (pArg->GetIsMissingOptions()) + m_setCmdArgsMissingInfo.push_back(const_cast(pArg)); + else if (!pArg->GetValid()) + m_setCmdArgsThatNotValid.push_back(const_cast(pArg)); + } + } + if (pArg->GetFound() && !pArg->GetIsHandledByCmd()) + { + m_bIsArgsPresentButNotHandledByCmd = true; + m_setCmdArgsNotHandledByCmd.push_back(const_cast(pArg)); + } + + // Next + ++it; + } + + // Check that one or more argument objects have any issues to report... + + if (nArgs < nArgsMandatoryCnt) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_N_OPTIONS_REQUIRED), nArgsMandatoryCnt)); + return MIstatus::failure; + } + + if (IsArgsPresentButNotHandledByCmd()) + WarningArgsNotHandledbyCmdLogFile(vStrMiCmd); + + return ValidationFormErrorMessages(vwCmdArgsText); } //++ ------------------------------------------------------------------------------------ -// Details: Having validated the command's options text and failed for some reason form -// the error message made up with the faults found. -// Type: Method. -// vCmdArgsText - (RW) A command's options or argument. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Having validated the command's options text and failed for some reason form +// the error message made up with the faults found. +// Type: Method. +// vCmdArgsText - (RW) A command's options or argument. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgSet::ValidationFormErrorMessages( const CMICmdArgContext & vwCmdArgsText ) +bool +CMICmdArgSet::ValidationFormErrorMessages(const CMICmdArgContext &vwCmdArgsText) { - CMIUtilString strListMissing; - CMIUtilString strListInvalid; - CMIUtilString strListMissingInfo; - const bool bArgsMissing = (m_setCmdArgsThatAreMissing.size() > 0); - const bool bArgsInvalid = (m_setCmdArgsThatNotValid.size() > 0); - const bool bArgsMissingInfo = (m_setCmdArgsMissingInfo.size() > 0); - if( !(bArgsMissing || bArgsInvalid || bArgsMissingInfo) ) - return MIstatus::success; - if( bArgsMissing ) - { - MIuint i = 0; - SetCmdArgs_t::const_iterator it = m_setCmdArgsThatAreMissing.begin(); - while( it != m_setCmdArgsThatAreMissing.end() ) - { - if( i++ > 0 ) - strListMissing += m_constStrCommaSpc; - - const CMICmdArgValBase * pArg( *it ); - strListMissing += pArg->GetName(); - - // Next - ++it; - } - } - if( bArgsInvalid ) - { - MIuint i = 0; - SetCmdArgs_t::const_iterator it = m_setCmdArgsThatNotValid.begin(); - while( it != m_setCmdArgsThatNotValid.end() ) - { - if( i++ > 0 ) - strListMissing += m_constStrCommaSpc; - - const CMICmdArgValBase * pArg( *it ); - strListInvalid += pArg->GetName(); - - // Next - ++it; - } - } - if( bArgsMissingInfo ) - { - MIuint i = 0; - SetCmdArgs_t::const_iterator it = m_setCmdArgsMissingInfo.begin(); - while( it != m_setCmdArgsMissingInfo.end() ) - { - if( i++ > 0 ) - strListMissingInfo += m_constStrCommaSpc; - - const CMICmdArgValBase * pArg( *it ); - strListMissingInfo += pArg->GetName(); - - // Next - ++it; - } - } - - bool bHaveOneError = false; - CMIUtilString strError = MIRSRC( IDS_CMD_ARGS_ERR_PREFIX_MSG ); - if( bArgsMissing && bArgsInvalid ) - { - bHaveOneError = true; - strError += CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID ), strListMissing.c_str(), strListInvalid.c_str() ); - } - if( bArgsMissing ) - { - if( bHaveOneError ) - strError += ". "; - bHaveOneError = true; - strError += CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY ), strListMissing.c_str() ); - } - if( bArgsMissingInfo ) - { - if( bHaveOneError ) - strError += ". "; - bHaveOneError = true; - strError += CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF ), strListMissingInfo.c_str() ); - } - if( bArgsInvalid ) - { - if( bHaveOneError ) - strError += ". "; - bHaveOneError = true; - strError += CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_VALIDATION_INVALID ), strListInvalid.c_str() ); - } - if( !vwCmdArgsText.IsEmpty() ) - { - if( bHaveOneError ) - strError += ". "; - bHaveOneError = true; - strError += CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN ), vwCmdArgsText.GetArgsLeftToParse().c_str() ); - } - - if( bHaveOneError ) - { - SetErrorDescription( strError ); - return MIstatus::failure; - } - - return MIstatus::success; + CMIUtilString strListMissing; + CMIUtilString strListInvalid; + CMIUtilString strListMissingInfo; + const bool bArgsMissing = (m_setCmdArgsThatAreMissing.size() > 0); + const bool bArgsInvalid = (m_setCmdArgsThatNotValid.size() > 0); + const bool bArgsMissingInfo = (m_setCmdArgsMissingInfo.size() > 0); + if (!(bArgsMissing || bArgsInvalid || bArgsMissingInfo)) + return MIstatus::success; + if (bArgsMissing) + { + MIuint i = 0; + SetCmdArgs_t::const_iterator it = m_setCmdArgsThatAreMissing.begin(); + while (it != m_setCmdArgsThatAreMissing.end()) + { + if (i++ > 0) + strListMissing += m_constStrCommaSpc; + + const CMICmdArgValBase *pArg(*it); + strListMissing += pArg->GetName(); + + // Next + ++it; + } + } + if (bArgsInvalid) + { + MIuint i = 0; + SetCmdArgs_t::const_iterator it = m_setCmdArgsThatNotValid.begin(); + while (it != m_setCmdArgsThatNotValid.end()) + { + if (i++ > 0) + strListMissing += m_constStrCommaSpc; + + const CMICmdArgValBase *pArg(*it); + strListInvalid += pArg->GetName(); + + // Next + ++it; + } + } + if (bArgsMissingInfo) + { + MIuint i = 0; + SetCmdArgs_t::const_iterator it = m_setCmdArgsMissingInfo.begin(); + while (it != m_setCmdArgsMissingInfo.end()) + { + if (i++ > 0) + strListMissingInfo += m_constStrCommaSpc; + + const CMICmdArgValBase *pArg(*it); + strListMissingInfo += pArg->GetName(); + + // Next + ++it; + } + } + + bool bHaveOneError = false; + CMIUtilString strError = MIRSRC(IDS_CMD_ARGS_ERR_PREFIX_MSG); + if (bArgsMissing && bArgsInvalid) + { + bHaveOneError = true; + strError += CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID), strListMissing.c_str(), strListInvalid.c_str()); + } + if (bArgsMissing) + { + if (bHaveOneError) + strError += ". "; + bHaveOneError = true; + strError += CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY), strListMissing.c_str()); + } + if (bArgsMissingInfo) + { + if (bHaveOneError) + strError += ". "; + bHaveOneError = true; + strError += CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF), strListMissingInfo.c_str()); + } + if (bArgsInvalid) + { + if (bHaveOneError) + strError += ". "; + bHaveOneError = true; + strError += CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_INVALID), strListInvalid.c_str()); + } + if (!vwCmdArgsText.IsEmpty()) + { + if (bHaveOneError) + strError += ". "; + bHaveOneError = true; + strError += CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN), vwCmdArgsText.GetArgsLeftToParse().c_str()); + } + + if (bHaveOneError) + { + SetErrorDescription(strError); + return MIstatus::failure; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Ask if the command's argument options text had any arguments. -// Type: Method. -// Args: None. -// Return: bool - True = Has one or more arguments present, false = no arguments. -// Throws: None. +// Details: Ask if the command's argument options text had any arguments. +// Type: Method. +// Args: None. +// Return: bool - True = Has one or more arguments present, false = no arguments. +// Throws: None. //-- -bool CMICmdArgSet::IsArgContextEmpty( void ) const +bool +CMICmdArgSet::IsArgContextEmpty(void) const { - return m_cmdArgContext.IsEmpty(); + return m_cmdArgContext.IsEmpty(); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the number of arguments that are being used for the command. -// Type: Method. -// Args: None. -// Return: MIuint - Argument count. -// Throws: None. +// Details: Retrieve the number of arguments that are being used for the command. +// Type: Method. +// Args: None. +// Return: MIuint - Argument count. +// Throws: None. //-- -MIuint CMICmdArgSet::GetCount( void ) const +MIuint +CMICmdArgSet::GetCount(void) const { - return m_setCmdArgs.size(); + return m_setCmdArgs.size(); } - + //++ ------------------------------------------------------------------------------------ -// Details: Given a set of command argument objects retrieve the argument with the -// specified name. -// Type: Method. -// Args: vpArg - (W) A pointer to a command's argument object. -// Return: True - Argument found. -// False - Argument not found. -// Throws: None. +// Details: Given a set of command argument objects retrieve the argument with the +// specified name. +// Type: Method. +// Args: vpArg - (W) A pointer to a command's argument object. +// Return: True - Argument found. +// False - Argument not found. +// Throws: None. //-- -bool CMICmdArgSet::GetArg( const CMIUtilString & vArgName, CMICmdArgValBase *& vpArg ) const +bool +CMICmdArgSet::GetArg(const CMIUtilString &vArgName, CMICmdArgValBase *&vpArg) const { - bool bFound = false; - SetCmdArgs_t::const_iterator it = m_setCmdArgs.begin(); - while( it != m_setCmdArgs.end() ) - { - CMICmdArgValBase * pArg( *it ); - if( pArg->GetName() == vArgName ) - { - bFound = true; - vpArg = pArg; - break; - } - - // Next - ++it; - } - - return bFound; + bool bFound = false; + SetCmdArgs_t::const_iterator it = m_setCmdArgs.begin(); + while (it != m_setCmdArgs.end()) + { + CMICmdArgValBase *pArg(*it); + if (pArg->GetName() == vArgName) + { + bFound = true; + vpArg = pArg; + break; + } + + // Next + ++it; + } + + return bFound; } - + //++ ------------------------------------------------------------------------------------ -// Details: Write a warning message to the MI Log file about the command's arguments or -// options that were found present but not handled. -// Type: Method. -// Args: vrCmdName - (R) The command's name. -// Return: None. -// Throws: None. +// Details: Write a warning message to the MI Log file about the command's arguments or +// options that were found present but not handled. +// Type: Method. +// Args: vrCmdName - (R) The command's name. +// Return: None. +// Throws: None. //-- -void CMICmdArgSet::WarningArgsNotHandledbyCmdLogFile( const CMIUtilString & vrCmdName ) +void +CMICmdArgSet::WarningArgsNotHandledbyCmdLogFile(const CMIUtilString &vrCmdName) { #if MICONFIG_GIVE_WARNING_CMD_ARGS_NOT_HANDLED - CMIUtilString strArgsNotHandled; - const CMICmdArgSet::SetCmdArgs_t & rSetArgs = GetArgsNotHandledByCmd(); - MIuint nCnt = 0; - CMICmdArgSet::SetCmdArgs_t::const_iterator it = rSetArgs.begin(); - while( it != rSetArgs.end() ) - { - if( nCnt++ > 0 ) - strArgsNotHandled += m_constStrCommaSpc; - const CMICmdArgValBase * pArg = *it; - strArgsNotHandled += pArg->GetName(); - - // Next - ++it; - } - - const CMIUtilString strWarningMsg( CMIUtilString::Format( MIRSRC( IDS_CMD_WRN_ARGS_NOT_HANDLED ), vrCmdName.c_str(), strArgsNotHandled.c_str() ) ); - m_pLog->WriteLog( strWarningMsg ); + CMIUtilString strArgsNotHandled; + const CMICmdArgSet::SetCmdArgs_t &rSetArgs = GetArgsNotHandledByCmd(); + MIuint nCnt = 0; + CMICmdArgSet::SetCmdArgs_t::const_iterator it = rSetArgs.begin(); + while (it != rSetArgs.end()) + { + if (nCnt++ > 0) + strArgsNotHandled += m_constStrCommaSpc; + const CMICmdArgValBase *pArg = *it; + strArgsNotHandled += pArg->GetName(); + + // Next + ++it; + } + + const CMIUtilString strWarningMsg( + CMIUtilString::Format(MIRSRC(IDS_CMD_WRN_ARGS_NOT_HANDLED), vrCmdName.c_str(), strArgsNotHandled.c_str())); + m_pLog->WriteLog(strWarningMsg); #endif // MICONFIG_GIVE_WARNING_CMD_ARGS_NOT_HANDLED } diff --git a/tools/lldb-mi/MICmdArgSet.h b/tools/lldb-mi/MICmdArgSet.h index 5f8f5049d9af..eed667071733 100644 --- a/tools/lldb-mi/MICmdArgSet.h +++ b/tools/lldb-mi/MICmdArgSet.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgSet.h +// File: MICmdArgSet.h // -// Overview: CMICmdArgSet interface. +// Overview: CMICmdArgSet interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -32,78 +32,81 @@ class CMICmdArgValBase; //++ ============================================================================ -// Details: MI common code class. Command arguments container class. -// A command may have one or more arguments of which some may be optional. -// *this class contains a list of the command's arguments which are -// validates against the commands argument options string (context string). -// Each argument tries to extract the value it is looking for. -// Argument objects added to *this container are owned by this container -// and are deleted when this container goes out of scope. Allocate argument -// objects on the heap. -// It is assummed the arguments to be parsed are read from left to right in -// order. The order added to *this container is the order they will parsed. -// Gotchas: None. -// Authors: Illya Rudkin 14/04/2014. -// Changes: None. +// Details: MI common code class. Command arguments container class. +// A command may have one or more arguments of which some may be optional. +// *this class contains a list of the command's arguments which are +// validates against the commands argument options string (context string). +// Each argument tries to extract the value it is looking for. +// Argument objects added to *this container are owned by this container +// and are deleted when this container goes out of scope. Allocate argument +// objects on the heap. +// It is assummed the arguments to be parsed are read from left to right in +// order. The order added to *this container is the order they will parsed. +// Gotchas: None. +// Authors: Illya Rudkin 14/04/2014. +// Changes: None. //-- class CMICmdArgSet : public CMICmnBase { -// Classes: -public: - //++ - // Description: ArgSet's interface for command arguments to implement. - //-- - class IArg - { - public: - virtual bool GetFound( void ) const = 0; - virtual bool GetIsHandledByCmd( void ) const = 0; - virtual bool GetIsMandatory( void ) const = 0; - virtual bool GetIsMissingOptions( void ) const = 0; - virtual const CMIUtilString & GetName( void ) const = 0; - virtual bool GetValid( void ) const = 0; - virtual bool Validate( CMICmdArgContext & vwArgContext ) = 0; - - /* dtor */ virtual ~IArg( void ) {}; - }; + // Classes: + public: + //++ + // Description: ArgSet's interface for command arguments to implement. + //-- + class IArg + { + public: + virtual bool GetFound(void) const = 0; + virtual bool GetIsHandledByCmd(void) const = 0; + virtual bool GetIsMandatory(void) const = 0; + virtual bool GetIsMissingOptions(void) const = 0; + virtual const CMIUtilString &GetName(void) const = 0; + virtual bool GetValid(void) const = 0; + virtual bool Validate(CMICmdArgContext &vwArgContext) = 0; -// Typedefs: -public: - typedef std::vector< CMICmdArgValBase * > SetCmdArgs_t; + /* dtor */ virtual ~IArg(void){}; + }; -// Methods: -public: - /* ctor */ CMICmdArgSet( void ); - - bool Add( const CMICmdArgValBase & vArg ); - bool GetArg( const CMIUtilString & vArgName, CMICmdArgValBase *& vpArg ) const; - const SetCmdArgs_t & GetArgsThatAreMissing( void ) const; - const SetCmdArgs_t & GetArgsThatInvalid( void ) const; - MIuint GetCount( void ) const; - bool IsArgContextEmpty( void ) const; - bool IsArgsPresentButNotHandledByCmd( void ) const; - void WarningArgsNotHandledbyCmdLogFile( const CMIUtilString & vrCmdName ); - bool Validate( const CMIUtilString & vStrMiCmd, CMICmdArgContext & vwCmdArgsText ); + // Typedefs: + public: + typedef std::vector SetCmdArgs_t; -// Overrideable: -public: - /* dtor */ virtual ~CMICmdArgSet( void ); + // Methods: + public: + /* ctor */ CMICmdArgSet(void); -// Methods: -private: - const SetCmdArgs_t & GetArgsNotHandledByCmd( void ) const; - void Destroy( void ); // Release resources used by *this object - bool ValidationFormErrorMessages( const CMICmdArgContext & vwCmdArgsText ); + bool Add(const CMICmdArgValBase &vArg); + bool GetArg(const CMIUtilString &vArgName, CMICmdArgValBase *&vpArg) const; + const SetCmdArgs_t &GetArgsThatAreMissing(void) const; + const SetCmdArgs_t &GetArgsThatInvalid(void) const; + MIuint GetCount(void) const; + bool IsArgContextEmpty(void) const; + bool IsArgsPresentButNotHandledByCmd(void) const; + void WarningArgsNotHandledbyCmdLogFile(const CMIUtilString &vrCmdName); + bool Validate(const CMIUtilString &vStrMiCmd, CMICmdArgContext &vwCmdArgsText); -// Attributes: -private: - bool m_bIsArgsPresentButNotHandledByCmd; // True = The driver's client presented the command with options recognised but not handled by a command, false = all args handled - SetCmdArgs_t m_setCmdArgs; // The set of arguments that are that the command is expecting to find in the options string - SetCmdArgs_t m_setCmdArgsThatAreMissing; // The set of arguments that are required by the command but are missing - SetCmdArgs_t m_setCmdArgsThatNotValid; // The set of arguments found in the text but for some reason unable to extract a value - SetCmdArgs_t m_setCmdArgsNotHandledByCmd; // The set of arguments specified by the command which were present to the command but not handled - SetCmdArgs_t m_setCmdArgsMissingInfo; // The set of arguments that were present but were found to be missing additional information i.e. --thread 3 but 3 is missing - CMICmdArgContext m_cmdArgContext; // Copy of the command's argument options text before validate takes place (empties it of content) - const CMIUtilString m_constStrCommaSpc; -}; + // Overrideable: + public: + /* dtor */ virtual ~CMICmdArgSet(void); + // Methods: + private: + const SetCmdArgs_t &GetArgsNotHandledByCmd(void) const; + void + Destroy(void); // Release resources used by *this object + bool ValidationFormErrorMessages(const CMICmdArgContext &vwCmdArgsText); + + // Attributes: + private: + bool m_bIsArgsPresentButNotHandledByCmd; // True = The driver's client presented the command with options recognised but not handled by + // a command, false = all args handled + SetCmdArgs_t m_setCmdArgs; // The set of arguments that are that the command is expecting to find in the options string + SetCmdArgs_t m_setCmdArgsThatAreMissing; // The set of arguments that are required by the command but are missing + SetCmdArgs_t m_setCmdArgsThatNotValid; // The set of arguments found in the text but for some reason unable to extract a value + SetCmdArgs_t + m_setCmdArgsNotHandledByCmd; // The set of arguments specified by the command which were present to the command but not handled + SetCmdArgs_t m_setCmdArgsMissingInfo; // The set of arguments that were present but were found to be missing additional information i.e. + // --thread 3 but 3 is missing + CMICmdArgContext m_cmdArgContext; // Copy of the command's argument options text before validate takes place (empties it of content) + const CMIUtilString m_constStrCommaSpc; +}; diff --git a/tools/lldb-mi/MICmdArgValBase.cpp b/tools/lldb-mi/MICmdArgValBase.cpp index ceab1a494865..1419df3206c8 100644 --- a/tools/lldb-mi/MICmdArgValBase.cpp +++ b/tools/lldb-mi/MICmdArgValBase.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValBase.cpp +// File: MICmdArgValBase.cpp // -// Overview: CMICmdArgValBase implementation. +// Overview: CMICmdArgValBase implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -25,147 +25,154 @@ #include "MICmdArgContext.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValBase constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValBase constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValBase::CMICmdArgValBase( void ) -: m_bFound( false ) -, m_bValid( false ) -, m_bMandatory( false ) -, m_bHandled( false ) -, m_bIsMissingOptions( false ) +CMICmdArgValBase::CMICmdArgValBase(void) + : m_bFound(false) + , m_bValid(false) + , m_bMandatory(false) + , m_bHandled(false) + , m_bIsMissingOptions(false) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValBase constructor. -// Type: Method. -// Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// Return: None. -// Throws: None. +// Details: CMICmdArgValBase constructor. +// Type: Method. +// Args: vrArgName - (R) Argument's name to search by. +// vbMandatory - (R) True = Yes must be present, false = optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// Return: None. +// Throws: None. //-- -CMICmdArgValBase::CMICmdArgValBase( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ) -: m_bFound( false ) -, m_bValid( false ) -, m_bMandatory( vbMandatory ) -, m_strArgName( vrArgName ) -, m_bHandled( vbHandleByCmd ) -, m_bIsMissingOptions( false ) +CMICmdArgValBase::CMICmdArgValBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) + : m_bFound(false) + , m_bValid(false) + , m_bMandatory(vbMandatory) + , m_strArgName(vrArgName) + , m_bHandled(vbHandleByCmd) + , m_bIsMissingOptions(false) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValBase destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValBase destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValBase::~CMICmdArgValBase( void ) +CMICmdArgValBase::~CMICmdArgValBase(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the state flag of whether the argument is handled by the command or -// not. -// Type: Method. -// Args: None. -// Return: True - Command needs more information. -// False - All information is present as expected. -// Throws: None. +// Details: Retrieve the state flag of whether the argument is handled by the command or +// not. +// Type: Method. +// Args: None. +// Return: True - Command needs more information. +// False - All information is present as expected. +// Throws: None. //-- -bool CMICmdArgValBase::GetIsMissingOptions( void ) const +bool +CMICmdArgValBase::GetIsMissingOptions(void) const { - return m_bIsMissingOptions; + return m_bIsMissingOptions; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the state flag of whether the argument is handled by the command or -// not. -// Type: Method. -// Args: None. -// Return: True - Command handles *this argument or option. -// False - Not handled (argument specified but ignored). -// Throws: None. +// Details: Retrieve the state flag of whether the argument is handled by the command or +// not. +// Type: Method. +// Args: None. +// Return: True - Command handles *this argument or option. +// False - Not handled (argument specified but ignored). +// Throws: None. //-- -bool CMICmdArgValBase::GetIsHandledByCmd( void ) const +bool +CMICmdArgValBase::GetIsHandledByCmd(void) const { - return m_bHandled; + return m_bHandled; } - + //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the name of *this argument. -// Type: Method. -// Args: None. -// Return: CMIUtilString & - Return the text name. -// Throws: None. +// Details: Retrieve the name of *this argument. +// Type: Method. +// Args: None. +// Return: CMIUtilString & - Return the text name. +// Throws: None. //-- -const CMIUtilString & CMICmdArgValBase::GetName( void ) const +const CMIUtilString & +CMICmdArgValBase::GetName(void) const { - return m_strArgName; + return m_strArgName; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the state flag of whether the argument was found in the command's -// argument / options string. -// Type: Method. -// Args: None. -// Return: True - Argument found. -// False - Argument not found. -// Throws: None. +// Details: Retrieve the state flag of whether the argument was found in the command's +// argument / options string. +// Type: Method. +// Args: None. +// Return: True - Argument found. +// False - Argument not found. +// Throws: None. //-- -bool CMICmdArgValBase::GetFound( void ) const +bool +CMICmdArgValBase::GetFound(void) const { - return m_bFound; + return m_bFound; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the state flag indicating whether the value was obtained from the -// text arguments string and is valid. -// Type: Method. -// Args: None. -// Return: True - Argument valid. -// False - Argument not valid. -// Throws: None. +// Details: Retrieve the state flag indicating whether the value was obtained from the +// text arguments string and is valid. +// Type: Method. +// Args: None. +// Return: True - Argument valid. +// False - Argument not valid. +// Throws: None. //-- -bool CMICmdArgValBase::GetValid( void ) const +bool +CMICmdArgValBase::GetValid(void) const { - return m_bValid; + return m_bValid; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the state flag indicating whether *this argument is a mandatory -// argument for the command or is optional to be present. -// Type: Method. -// Args: None. -// Return: True - Mandatory. -// False - Optional. -// Throws: None. +// Details: Retrieve the state flag indicating whether *this argument is a mandatory +// argument for the command or is optional to be present. +// Type: Method. +// Args: None. +// Return: True - Mandatory. +// False - Optional. +// Throws: None. //-- -bool CMICmdArgValBase::GetIsMandatory( void ) const +bool +CMICmdArgValBase::GetIsMandatory(void) const { - return m_bMandatory; + return m_bMandatory; } //++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the value *this -// argument is looking for. -// Type: Overrideable. -// Args: vArgContext - (RW) The command's argument options string. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Parse the command's argument options string and try to extract the value *this +// argument is looking for. +// Type: Overrideable. +// Args: vArgContext - (RW) The command's argument options string. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgValBase::Validate( CMICmdArgContext & vwArgContext ) +bool +CMICmdArgValBase::Validate(CMICmdArgContext &vwArgContext) { - MIunused( vwArgContext ); + MIunused(vwArgContext); - // Override to implement + // Override to implement - return MIstatus::failure; -} \ No newline at end of file + return MIstatus::failure; +} diff --git a/tools/lldb-mi/MICmdArgValBase.h b/tools/lldb-mi/MICmdArgValBase.h index b367cb88ce29..0afe8d9bab6a 100644 --- a/tools/lldb-mi/MICmdArgValBase.h +++ b/tools/lldb-mi/MICmdArgValBase.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValBase.h +// File: MICmdArgValBase.h // -// Overview: CMICmdArgValBase interface. +// Overview: CMICmdArgValBase interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -26,132 +26,130 @@ #include "MICmdArgSet.h" //++ ============================================================================ -// Details: MI common code class. Command argument base class. Arguments objects -// needing specialization derived from *this class. An argument knows -// what type of argument it is and how it is to interpret the options -// (context) string to find and validate a matching argument and so -// extract a value from it. -// Argument objects are added to the CMICmdArgSet container object. -// Once added the container they belong to that contain and will be -// deleted when the container goes out of scope. Allocate argument -// objects on the heap and pass in to the Add(). -// Note the code is written such that a command will produce an error -// should it be presented with arguments or options it does not understand. -// A command can recognise an option or argument then ignore if it -// wishes (a warning is sent to the MI's Log file). This is so it is -// hardwired to fail and catch arguments or options that presented by -// different driver clients. -// Based on the Interpreter pattern. -// Gotchas: None. -// Authors: Illya Rudkin 14/04/2014. -// Changes: None. +// Details: MI common code class. Command argument base class. Arguments objects +// needing specialization derived from *this class. An argument knows +// what type of argument it is and how it is to interpret the options +// (context) string to find and validate a matching argument and so +// extract a value from it. +// Argument objects are added to the CMICmdArgSet container object. +// Once added the container they belong to that contain and will be +// deleted when the container goes out of scope. Allocate argument +// objects on the heap and pass in to the Add(). +// Note the code is written such that a command will produce an error +// should it be presented with arguments or options it does not understand. +// A command can recognise an option or argument then ignore if it +// wishes (a warning is sent to the MI's Log file). This is so it is +// hardwired to fail and catch arguments or options that presented by +// different driver clients. +// Based on the Interpreter pattern. +// Gotchas: None. +// Authors: Illya Rudkin 14/04/2014. +// Changes: None. //-- class CMICmdArgValBase : public CMICmdArgSet::IArg { -// Methods: -public: - /* ctor */ CMICmdArgValBase( void ); - /* ctor */ CMICmdArgValBase( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ); - -// Overrideable: -public: - /* dtor */ virtual ~CMICmdArgValBase( void ); + // Methods: + public: + /* ctor */ CMICmdArgValBase(void); + /* ctor */ CMICmdArgValBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); -// Overridden: -public: - // From CMICmdArgSet::IArg - virtual bool GetFound( void ) const; - virtual bool GetIsHandledByCmd( void ) const; - virtual bool GetIsMandatory( void ) const; - virtual bool GetIsMissingOptions( void ) const; - virtual const CMIUtilString & GetName( void ) const; - virtual bool GetValid( void ) const; - virtual bool Validate( CMICmdArgContext & vwArgContext ); + // Overrideable: + public: + /* dtor */ virtual ~CMICmdArgValBase(void); -// Attributes: -protected: - bool m_bFound; // True = yes found in arguments options text, false = not found - bool m_bValid; // True = yes argument parsed and valid, false = not valid - bool m_bMandatory; // True = yes arg must be present, false = optional argument - CMIUtilString m_strArgName; - bool m_bHandled; // True = Command processes *this option, false = not handled - bool m_bIsMissingOptions; // True = Command needs more information, false = ok + // Overridden: + public: + // From CMICmdArgSet::IArg + virtual bool GetFound(void) const; + virtual bool GetIsHandledByCmd(void) const; + virtual bool GetIsMandatory(void) const; + virtual bool GetIsMissingOptions(void) const; + virtual const CMIUtilString &GetName(void) const; + virtual bool GetValid(void) const; + virtual bool Validate(CMICmdArgContext &vwArgContext); + + // Attributes: + protected: + bool m_bFound; // True = yes found in arguments options text, false = not found + bool m_bValid; // True = yes argument parsed and valid, false = not valid + bool m_bMandatory; // True = yes arg must be present, false = optional argument + CMIUtilString m_strArgName; + bool m_bHandled; // True = Command processes *this option, false = not handled + bool m_bIsMissingOptions; // True = Command needs more information, false = ok }; //++ ============================================================================ -// Details: MI common code class. Templated command argument base class. -// Gotchas: None. -// Authors: Illya Rudkin 14/04/2014. -// Changes: None. +// Details: MI common code class. Templated command argument base class. +// Gotchas: None. +// Authors: Illya Rudkin 14/04/2014. +// Changes: None. //-- -template< class T > -class CMICmdArgValBaseTemplate : public CMICmdArgValBase +template class CMICmdArgValBaseTemplate : public CMICmdArgValBase { -// Methods: -public: - /* ctor */ CMICmdArgValBaseTemplate( void ); - /* ctor */ CMICmdArgValBaseTemplate( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ); - // - const T & GetValue( void ) const; + // Methods: + public: + /* ctor */ CMICmdArgValBaseTemplate(void); + /* ctor */ CMICmdArgValBaseTemplate(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); + // + const T &GetValue(void) const; -// Overrideable: -public: - /* dtor */ virtual ~CMICmdArgValBaseTemplate( void ); + // Overrideable: + public: + /* dtor */ virtual ~CMICmdArgValBaseTemplate(void); -// Attributes: -protected: - T m_argValue; + // Attributes: + protected: + T m_argValue; }; //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValBaseTemplate constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValBaseTemplate constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -template< class T > -CMICmdArgValBaseTemplate< T >::CMICmdArgValBaseTemplate( void ) +template CMICmdArgValBaseTemplate::CMICmdArgValBaseTemplate(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValBaseTemplate constructor. -// Type: Method. -// Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// Return: None. -// Throws: None. +// Details: CMICmdArgValBaseTemplate constructor. +// Type: Method. +// Args: vrArgName - (R) Argument's name to search by. +// vbMandatory - (R) True = Yes must be present, false = optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// Return: None. +// Throws: None. //-- -template< class T > -CMICmdArgValBaseTemplate< T >::CMICmdArgValBaseTemplate( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ) -: CMICmdArgValBase( vrArgName, vbMandatory, vbHandleByCmd ) +template +CMICmdArgValBaseTemplate::CMICmdArgValBaseTemplate(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) + : CMICmdArgValBase(vrArgName, vbMandatory, vbHandleByCmd) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValBaseTemplate destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValBaseTemplate destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -template< class T > -CMICmdArgValBaseTemplate< T >::~CMICmdArgValBaseTemplate( void ) +template CMICmdArgValBaseTemplate::~CMICmdArgValBaseTemplate(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the value the argument parsed from the command's argument / options -// text string. -// Type: Method. -// Args: None. -// Return: Template type & - The arg value of *this object. -// Throws: None. +// Details: Retrieve the value the argument parsed from the command's argument / options +// text string. +// Type: Method. +// Args: None. +// Return: Template type & - The arg value of *this object. +// Throws: None. //-- -template< class T > -const T & CMICmdArgValBaseTemplate< T >::GetValue( void ) const +template +const T & +CMICmdArgValBaseTemplate::GetValue(void) const { - return m_argValue; + return m_argValue; } diff --git a/tools/lldb-mi/MICmdArgValConsume.cpp b/tools/lldb-mi/MICmdArgValConsume.cpp index 72a57f870ad4..3a01db4bc4f8 100644 --- a/tools/lldb-mi/MICmdArgValConsume.cpp +++ b/tools/lldb-mi/MICmdArgValConsume.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValConsume.cpp +// File: MICmdArgValConsume.cpp // -// Overview: CMICmdArgValConsume implementation. +// Overview: CMICmdArgValConsume implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -24,96 +24,98 @@ #include "MICmdArgContext.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValConsume constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValConsume constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValConsume::CMICmdArgValConsume( void ) +CMICmdArgValConsume::CMICmdArgValConsume(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValConsume constructor. -// Type: Method. -// Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// Return: None. -// Throws: None. +// Details: CMICmdArgValConsume constructor. +// Type: Method. +// Args: vrArgName - (R) Argument's name to search by. +// vbMandatory - (R) True = Yes must be present, false = optional argument. +// Return: None. +// Throws: None. //-- -CMICmdArgValConsume::CMICmdArgValConsume( const CMIUtilString & vrArgName, const bool vbMandatory ) -: CMICmdArgValBaseTemplate( vrArgName, vbMandatory, true ) +CMICmdArgValConsume::CMICmdArgValConsume(const CMIUtilString &vrArgName, const bool vbMandatory) + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, true) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValConsume destructor. -// Type: Overidden. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValConsume destructor. +// Type: Overidden. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValConsume::~CMICmdArgValConsume( void ) +CMICmdArgValConsume::~CMICmdArgValConsume(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the value *this -// argument is looking for. -// Type: Overridden. -// Args: vwArgContext - (R) The command's argument options string. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Parse the command's argument options string and try to extract the value *this +// argument is looking for. +// Type: Overridden. +// Args: vwArgContext - (R) The command's argument options string. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgValConsume::Validate( CMICmdArgContext & vwArgContext ) +bool +CMICmdArgValConsume::Validate(CMICmdArgContext &vwArgContext) { - if( vwArgContext.IsEmpty() ) - return MIstatus::success; + if (vwArgContext.IsEmpty()) + return MIstatus::success; - if( vwArgContext.GetNumberArgsPresent() == 1 ) - { - const CMIUtilString & rArg( vwArgContext.GetArgsLeftToParse() ); - m_bFound = true; - m_bValid = true; - vwArgContext.RemoveArg( rArg ); - return MIstatus::success; - } - - // In reality there are more than one option, if so the file option - // is the last one (don't handle that here - find the best looking one) - const CMIUtilString::VecString_t vecOptions( vwArgContext.GetArgs() ); - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while( it != vecOptions.end() ) - { - const CMIUtilString & rTxt( *it ); - m_bFound = true; - - if( vwArgContext.RemoveArg( rTxt ) ) - { - m_bValid = true; - return MIstatus::success; - } - else - return MIstatus::success; - - // Next - ++it; - } + if (vwArgContext.GetNumberArgsPresent() == 1) + { + const CMIUtilString &rArg(vwArgContext.GetArgsLeftToParse()); + m_bFound = true; + m_bValid = true; + vwArgContext.RemoveArg(rArg); + return MIstatus::success; + } - return MIstatus::failure; + // In reality there are more than one option, if so the file option + // is the last one (don't handle that here - find the best looking one) + const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) + { + const CMIUtilString &rTxt(*it); + m_bFound = true; + + if (vwArgContext.RemoveArg(rTxt)) + { + m_bValid = true; + return MIstatus::success; + } + else + return MIstatus::success; + + // Next + ++it; + } + + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Nothing to examine as we just want to consume the argument or option (ignore -// it). -// Type: Method. -// Args: None. -// Return: bool - True = yes ok, false = not ok. -// Throws: None. +// Details: Nothing to examine as we just want to consume the argument or option (ignore +// it). +// Type: Method. +// Args: None. +// Return: bool - True = yes ok, false = not ok. +// Throws: None. //-- -bool CMICmdArgValConsume::IsOk( void ) const +bool +CMICmdArgValConsume::IsOk(void) const { - return true; + return true; } diff --git a/tools/lldb-mi/MICmdArgValConsume.h b/tools/lldb-mi/MICmdArgValConsume.h index a113d89458f3..2b26e33aa8c1 100644 --- a/tools/lldb-mi/MICmdArgValConsume.h +++ b/tools/lldb-mi/MICmdArgValConsume.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValConsume.h +// File: MICmdArgValConsume.h // -// Overview: CMICmdArgValConsume interface. +// Overview: CMICmdArgValConsume interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -28,36 +28,36 @@ class CMICmdArgContext; //++ ============================================================================ -// Details: MI common code class. Command argument class. Arguments object -// needing specialization derived from the CMICmdArgValBase class. -// An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching -// argument. This type having recognised its argument name just consumes -// that argument or option (ignores it). This is the so the validation -// process can then ask if all arguments or options have been recognised -// other an error will occurred "argument not recognised". For example -// this can be used to consume the "--" text which is not an argument in -// itself. Normally the GetValue() function (in base class) would return -// a value for the argument but is not the case for *this argument type -// object. -// Based on the Interpreter pattern. -// Gotchas: None. -// Authors: Illya Rudkin 20/05/2014. -// Changes: None. +// Details: MI common code class. Command argument class. Arguments object +// needing specialization derived from the CMICmdArgValBase class. +// An argument knows what type of argument it is and how it is to +// interpret the options (context) string to find and validate a matching +// argument. This type having recognised its argument name just consumes +// that argument or option (ignores it). This is the so the validation +// process can then ask if all arguments or options have been recognised +// other an error will occurred "argument not recognised". For example +// this can be used to consume the "--" text which is not an argument in +// itself. Normally the GetValue() function (in base class) would return +// a value for the argument but is not the case for *this argument type +// object. +// Based on the Interpreter pattern. +// Gotchas: None. +// Authors: Illya Rudkin 20/05/2014. +// Changes: None. //-- -class CMICmdArgValConsume : public CMICmdArgValBaseTemplate< CMIUtilString > +class CMICmdArgValConsume : public CMICmdArgValBaseTemplate { -// Methods: -public: - /* ctor */ CMICmdArgValConsume( void ); - /* ctor */ CMICmdArgValConsume( const CMIUtilString & vrArgName, const bool vbMandatory ); - // - bool IsOk( void ) const; + // Methods: + public: + /* ctor */ CMICmdArgValConsume(void); + /* ctor */ CMICmdArgValConsume(const CMIUtilString &vrArgName, const bool vbMandatory); + // + bool IsOk(void) const; -// Overridden: -public: - // From CMICmdArgValBase - /* dtor */ virtual ~CMICmdArgValConsume( void ); - // From CMICmdArgSet::IArg - virtual bool Validate( CMICmdArgContext & vwArgContext ); + // Overridden: + public: + // From CMICmdArgValBase + /* dtor */ virtual ~CMICmdArgValConsume(void); + // From CMICmdArgSet::IArg + virtual bool Validate(CMICmdArgContext &vwArgContext); }; diff --git a/tools/lldb-mi/MICmdArgValFile.cpp b/tools/lldb-mi/MICmdArgValFile.cpp index d5cc52b90b44..cee811f24dee 100644 --- a/tools/lldb-mi/MICmdArgValFile.cpp +++ b/tools/lldb-mi/MICmdArgValFile.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValFile.cpp +// File: MICmdArgValFile.cpp // -// Overview: CMICmdArgValFile implementation. +// Overview: CMICmdArgValFile implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -24,181 +24,185 @@ #include "MICmdArgContext.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValFile constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValFile constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValFile::CMICmdArgValFile( void ) +CMICmdArgValFile::CMICmdArgValFile(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValFile constructor. -// Type: Method. -// Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// Return: None. -// Throws: None. +// Details: CMICmdArgValFile constructor. +// Type: Method. +// Args: vrArgName - (R) Argument's name to search by. +// vbMandatory - (R) True = Yes must be present, false = optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// Return: None. +// Throws: None. //-- -CMICmdArgValFile::CMICmdArgValFile( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ) -: CMICmdArgValBaseTemplate( vrArgName, vbMandatory, vbHandleByCmd ) +CMICmdArgValFile::CMICmdArgValFile(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValFile destructor. -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValFile destructor. +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValFile::~CMICmdArgValFile( void ) +CMICmdArgValFile::~CMICmdArgValFile(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the value *this -// argument is looking for. -// Type: Overridden. -// Args: vwArgContext - (R) The command's argument options string. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Parse the command's argument options string and try to extract the value *this +// argument is looking for. +// Type: Overridden. +// Args: vwArgContext - (R) The command's argument options string. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgValFile::Validate( CMICmdArgContext & vwArgContext ) +bool +CMICmdArgValFile::Validate(CMICmdArgContext &vwArgContext) { - if( vwArgContext.IsEmpty() ) - return MIstatus::success; - - // The GDB/MI spec suggests there is only parameter - - if( vwArgContext.GetNumberArgsPresent() == 1 ) - { - const CMIUtilString & rFile( vwArgContext.GetArgsLeftToParse() ); - if( IsFilePath( rFile ) ) - { - m_bFound = true; - m_bValid = true; - m_argValue = rFile.Trim( '"' ); - vwArgContext.RemoveArg( rFile ); - return MIstatus::success; - } - else - return MIstatus::failure; - } - - // In reality there are more than one option, if so the file option - // is the last one (don't handle that here - find the best looking one) - const CMIUtilString::VecString_t vecOptions( vwArgContext.GetArgs() ); - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while( it != vecOptions.end() ) - { - const CMIUtilString & rTxt( *it ); - if( IsFilePath( rTxt ) ) - { - m_bFound = true; - - if( vwArgContext.RemoveArg( rTxt ) ) - { - m_bValid = true; - m_argValue = rTxt.Trim( '"' ); - return MIstatus::success; - } - else - return MIstatus::success; - } - - // Next - ++it; - } - - return MIstatus::failure; + if (vwArgContext.IsEmpty()) + return MIstatus::success; + + // The GDB/MI spec suggests there is only parameter + + if (vwArgContext.GetNumberArgsPresent() == 1) + { + const CMIUtilString &rFile(vwArgContext.GetArgsLeftToParse()); + if (IsFilePath(rFile)) + { + m_bFound = true; + m_bValid = true; + m_argValue = rFile.Trim('"'); + vwArgContext.RemoveArg(rFile); + return MIstatus::success; + } + else + return MIstatus::failure; + } + + // In reality there are more than one option, if so the file option + // is the last one (don't handle that here - find the best looking one) + const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) + { + const CMIUtilString &rTxt(*it); + if (IsFilePath(rTxt)) + { + m_bFound = true; + + if (vwArgContext.RemoveArg(rTxt)) + { + m_bValid = true; + m_argValue = rTxt.Trim('"'); + return MIstatus::success; + } + else + return MIstatus::success; + } + + // Next + ++it; + } + + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Given some text extract the file name path from it. If a space is found in -// path done return the path surrounded in quotes. -// Type: Method. -// Args: vrTxt - (R) The text to extract the file name path from. -// Return: CMIUtilString - File name and or path. -// Throws: None. +// Details: Given some text extract the file name path from it. If a space is found in +// path done return the path surrounded in quotes. +// Type: Method. +// Args: vrTxt - (R) The text to extract the file name path from. +// Return: CMIUtilString - File name and or path. +// Throws: None. //-- -CMIUtilString CMICmdArgValFile::GetFileNamePath( const CMIUtilString & vrTxt ) const +CMIUtilString +CMICmdArgValFile::GetFileNamePath(const CMIUtilString &vrTxt) const { - CMIUtilString fileNamePath( vrTxt ); - - // Look for a space in the path - const MIchar cSpace = ' '; - const MIint nPos = fileNamePath.find( cSpace ); - if( nPos != (MIint) std::string::npos ) - fileNamePath = CMIUtilString::Format( "\"%s\"", fileNamePath.c_str() ); - - return fileNamePath; + CMIUtilString fileNamePath(vrTxt); + + // Look for a space in the path + const MIchar cSpace = ' '; + const MIint nPos = fileNamePath.find(cSpace); + if (nPos != (MIint)std::string::npos) + fileNamePath = CMIUtilString::Format("\"%s\"", fileNamePath.c_str()); + + return fileNamePath; } //++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid file name path. -// Type: Method. -// Args: vrFileNamePath - (R) File's name and directory path. -// Return: bool - True = yes valid file path, false = no. -// Throws: None. +// Details: Examine the string and determine if it is a valid file name path. +// Type: Method. +// Args: vrFileNamePath - (R) File's name and directory path. +// Return: bool - True = yes valid file path, false = no. +// Throws: None. //-- -bool CMICmdArgValFile::IsFilePath( const CMIUtilString & vrFileNamePath ) const +bool +CMICmdArgValFile::IsFilePath(const CMIUtilString &vrFileNamePath) const { - if( vrFileNamePath.empty() ) - return false; - - const bool bHavePosSlash = (vrFileNamePath.find_first_of( "/" ) != std::string::npos); - const bool bHaveBckSlash = (vrFileNamePath.find_first_of( "\\" ) != std::string::npos); - - // Look for --someLongOption - MIint nPos = vrFileNamePath.find_first_of( "--" ); - const bool bLong = (nPos == 0); - if( bLong ) - return false; - - // Look for -f type short parameters - nPos = vrFileNamePath.find_first_of( "-" ); - const bool bShort = (nPos == 0); - if( bShort ) - return false; - - // Look for i1 i2 i3.... - nPos = vrFileNamePath.find_first_of( "i" ); - const bool bFoundI1 = ((nPos == 0) && (::isdigit( vrFileNamePath[ 1 ] )) ); - if( bFoundI1 ) - return false; - - const bool bValidChars = IsValidChars( vrFileNamePath ); - if( bValidChars || bHavePosSlash || bHaveBckSlash ) - return true; - - return false; + if (vrFileNamePath.empty()) + return false; + + const bool bHavePosSlash = (vrFileNamePath.find_first_of("/") != std::string::npos); + const bool bHaveBckSlash = (vrFileNamePath.find_first_of("\\") != std::string::npos); + + // Look for --someLongOption + MIint nPos = vrFileNamePath.find_first_of("--"); + const bool bLong = (nPos == 0); + if (bLong) + return false; + + // Look for -f type short parameters + nPos = vrFileNamePath.find_first_of("-"); + const bool bShort = (nPos == 0); + if (bShort) + return false; + + // Look for i1 i2 i3.... + nPos = vrFileNamePath.find_first_of("i"); + const bool bFoundI1 = ((nPos == 0) && (::isdigit(vrFileNamePath[1]))); + if (bFoundI1) + return false; + + const bool bValidChars = IsValidChars(vrFileNamePath); + if (bValidChars || bHavePosSlash || bHaveBckSlash) + return true; + + return false; } //++ ------------------------------------------------------------------------------------ -// Details: Determine if the path contains valid characters for a file path. Letters can be -// either upper or lower case. -// Type: Method. -// Args: vrText - (R) The text data to examine. -// Return: bool - True = yes valid, false = one or more chars is valid. -// Throws: None. +// Details: Determine if the path contains valid characters for a file path. Letters can be +// either upper or lower case. +// Type: Method. +// Args: vrText - (R) The text data to examine. +// Return: bool - True = yes valid, false = one or more chars is valid. +// Throws: None. //-- -bool CMICmdArgValFile::IsValidChars( const CMIUtilString & vrText ) const +bool +CMICmdArgValFile::IsValidChars(const CMIUtilString &vrText) const { - const MIchar * pPtr = const_cast< MIchar * >( vrText.c_str() ); - for( MIuint i = 0; i < vrText.length(); i++, pPtr++ ) - { - const MIchar c = *pPtr; - if( ::isalnum( (int) c ) == 0 ) - { - if( (c != '.') && (c != '-') && (c != '_') ) - return false; - } - } - - return true; + const MIchar *pPtr = const_cast(vrText.c_str()); + for (MIuint i = 0; i < vrText.length(); i++, pPtr++) + { + const MIchar c = *pPtr; + if (::isalnum((int)c) == 0) + { + if ((c != '.') && (c != '-') && (c != '_')) + return false; + } + } + + return true; } diff --git a/tools/lldb-mi/MICmdArgValFile.h b/tools/lldb-mi/MICmdArgValFile.h index 071727401454..db5380885783 100644 --- a/tools/lldb-mi/MICmdArgValFile.h +++ b/tools/lldb-mi/MICmdArgValFile.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValFile.h +// File: MICmdArgValFile.h // -// Overview: CMICmdArgValFile interface. +// Overview: CMICmdArgValFile interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -28,34 +28,34 @@ class CMICmdArgContext; //++ ============================================================================ -// Details: MI common code class. Command argument class. Arguments object -// needing specialization derived from the CMICmdArgValBase class. -// An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching -// argument and so extract a value from it . -// Based on the Interpreter pattern. -// Gotchas: None. -// Authors: Illya Rudkin 15/04/2014. -// Changes: None. +// Details: MI common code class. Command argument class. Arguments object +// needing specialization derived from the CMICmdArgValBase class. +// An argument knows what type of argument it is and how it is to +// interpret the options (context) string to find and validate a matching +// argument and so extract a value from it . +// Based on the Interpreter pattern. +// Gotchas: None. +// Authors: Illya Rudkin 15/04/2014. +// Changes: None. //-- -class CMICmdArgValFile : public CMICmdArgValBaseTemplate< CMIUtilString > +class CMICmdArgValFile : public CMICmdArgValBaseTemplate { -// Methods: -public: - /* ctor */ CMICmdArgValFile( void ); - /* ctor */ CMICmdArgValFile( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ); - // - bool IsFilePath( const CMIUtilString & vrFileNamePath ) const; - CMIUtilString GetFileNamePath( const CMIUtilString & vrTxt ) const; + // Methods: + public: + /* ctor */ CMICmdArgValFile(void); + /* ctor */ CMICmdArgValFile(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); + // + bool IsFilePath(const CMIUtilString &vrFileNamePath) const; + CMIUtilString GetFileNamePath(const CMIUtilString &vrTxt) const; -// Overridden: -public: - // From CMICmdArgValBase - /* dtor */ virtual ~CMICmdArgValFile( void ); - // From CMICmdArgSet::IArg - virtual bool Validate( CMICmdArgContext & vwArgContext ); + // Overridden: + public: + // From CMICmdArgValBase + /* dtor */ virtual ~CMICmdArgValFile(void); + // From CMICmdArgSet::IArg + virtual bool Validate(CMICmdArgContext &vwArgContext); -// Methods: -private: - bool IsValidChars( const CMIUtilString & vrText ) const; + // Methods: + private: + bool IsValidChars(const CMIUtilString &vrText) const; }; diff --git a/tools/lldb-mi/MICmdArgValListBase.cpp b/tools/lldb-mi/MICmdArgValListBase.cpp index 37b729e42741..b992b307e346 100644 --- a/tools/lldb-mi/MICmdArgValListBase.cpp +++ b/tools/lldb-mi/MICmdArgValListBase.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValListBase.cpp +// File: MICmdArgValListBase.cpp // -// Overview: CMICmdArgValListBase implementation. +// Overview: CMICmdArgValListBase implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -31,191 +31,195 @@ #include "MICmdArgValConsume.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValListBase constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValListBase constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValListBase::CMICmdArgValListBase( void ) -: m_eArgType( eArgValType_invalid ) +CMICmdArgValListBase::CMICmdArgValListBase(void) + : m_eArgType(eArgValType_invalid) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValListBase constructor. -// Type: Method. -// Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// Return: None. -// Throws: None. +// Details: CMICmdArgValListBase constructor. +// Type: Method. +// Args: vrArgName - (R) Argument's name to search by. +// vbMandatory - (R) True = Yes must be present, false = optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// Return: None. +// Throws: None. //-- -CMICmdArgValListBase::CMICmdArgValListBase( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ) -: CMICmdArgValBaseTemplate( vrArgName, vbMandatory, vbHandleByCmd ) -, m_eArgType( eArgValType_invalid ) +CMICmdArgValListBase::CMICmdArgValListBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) + , m_eArgType(eArgValType_invalid) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValListBase constructor. -// Type: Method. -// Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// veType - (R) The type of argument to look for and create argument object of a certain type. -// Return: None. -// Throws: None. +// Details: CMICmdArgValListBase constructor. +// Type: Method. +// Args: vrArgName - (R) Argument's name to search by. +// vbMandatory - (R) True = Yes must be present, false = optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// veType - (R) The type of argument to look for and create argument object of a certain type. +// Return: None. +// Throws: None. //-- -CMICmdArgValListBase::CMICmdArgValListBase( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType ) -: CMICmdArgValBaseTemplate( vrArgName, vbMandatory, vbHandleByCmd ) -, m_eArgType( veType ) +CMICmdArgValListBase::CMICmdArgValListBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, + const ArgValType_e veType) + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) + , m_eArgType(veType) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValListBase destructor. -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValListBase destructor. +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValListBase::~CMICmdArgValListBase( void ) +CMICmdArgValListBase::~CMICmdArgValListBase(void) { - // Tidy up - Destroy(); + // Tidy up + Destroy(); } //++ ------------------------------------------------------------------------------------ -// Details: Tear down resources used by *this object. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: Tear down resources used by *this object. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMICmdArgValListBase::Destroy( void ) +void +CMICmdArgValListBase::Destroy(void) { - // Tidy up - VecArgObjPtr_t::const_iterator it = m_argValue.begin(); - while( it != m_argValue.end() ) - { - CMICmdArgValBase * pArgObj = *it; - delete pArgObj; + // Tidy up + VecArgObjPtr_t::const_iterator it = m_argValue.begin(); + while (it != m_argValue.end()) + { + CMICmdArgValBase *pArgObj = *it; + delete pArgObj; - // Next - ++it; - } - m_argValue.clear(); + // Next + ++it; + } + m_argValue.clear(); } //++ ------------------------------------------------------------------------------------ -// Details: Create an CMICmdArgValBase derived object matching the type specified -// and put the option or argument's value inside it. -// Type: Method. -// Args: vrTxt - (R) Text version the option or argument. -// veType - (R) The type of argument or option object to create. -// Return: CMICmdArgValBase * - Option object holding the value. -// - NULL = Functional failed. -// Throws: None. +// Details: Create an CMICmdArgValBase derived object matching the type specified +// and put the option or argument's value inside it. +// Type: Method. +// Args: vrTxt - (R) Text version the option or argument. +// veType - (R) The type of argument or option object to create. +// Return: CMICmdArgValBase * - Option object holding the value. +// - NULL = Functional failed. +// Throws: None. //-- -CMICmdArgValBase * CMICmdArgValListBase::CreationObj( const CMIUtilString & vrTxt, const ArgValType_e veType ) const +CMICmdArgValBase * +CMICmdArgValListBase::CreationObj(const CMIUtilString &vrTxt, const ArgValType_e veType) const { - CMICmdArgValBase * pOptionObj = nullptr; - switch( veType ) - { - case eArgValType_File: - pOptionObj = new CMICmdArgValFile(); - break; - case eArgValType_Consume: - pOptionObj = new CMICmdArgValConsume(); - break; - case eArgValType_Number: - pOptionObj = new CMICmdArgValNumber(); - break; - case eArgValType_OptionLong: - pOptionObj = new CMICmdArgValOptionLong(); - break; - case eArgValType_OptionShort: - pOptionObj = new CMICmdArgValOptionShort(); - break; - case eArgValType_String: - pOptionObj = new CMICmdArgValString(); - break; - case eArgValType_StringQuoted: - pOptionObj = new CMICmdArgValString( true, false, false ); - break; - case eArgValType_StringQuotedNumber: - pOptionObj = new CMICmdArgValString( true, true, false ); - break; - case eArgValType_StringQuotedNumberPath: - pOptionObj = new CMICmdArgValString( true, true, true ); - break; - case eArgValType_StringAnything: - pOptionObj = new CMICmdArgValString( true ); - break; - case eArgValType_ThreadGrp: - pOptionObj = new CMICmdArgValThreadGrp(); - break; - default: - return nullptr; - } + CMICmdArgValBase *pOptionObj = nullptr; + switch (veType) + { + case eArgValType_File: + pOptionObj = new CMICmdArgValFile(); + break; + case eArgValType_Consume: + pOptionObj = new CMICmdArgValConsume(); + break; + case eArgValType_Number: + pOptionObj = new CMICmdArgValNumber(); + break; + case eArgValType_OptionLong: + pOptionObj = new CMICmdArgValOptionLong(); + break; + case eArgValType_OptionShort: + pOptionObj = new CMICmdArgValOptionShort(); + break; + case eArgValType_String: + pOptionObj = new CMICmdArgValString(); + break; + case eArgValType_StringQuoted: + pOptionObj = new CMICmdArgValString(true, false, false); + break; + case eArgValType_StringQuotedNumber: + pOptionObj = new CMICmdArgValString(true, true, false); + break; + case eArgValType_StringQuotedNumberPath: + pOptionObj = new CMICmdArgValString(true, true, true); + break; + case eArgValType_StringAnything: + pOptionObj = new CMICmdArgValString(true); + break; + case eArgValType_ThreadGrp: + pOptionObj = new CMICmdArgValThreadGrp(); + break; + default: + return nullptr; + } - CMICmdArgContext argCntxt( vrTxt ); - if( !pOptionObj->Validate( argCntxt ) ) - return nullptr; + CMICmdArgContext argCntxt(vrTxt); + if (!pOptionObj->Validate(argCntxt)) + return nullptr; - return pOptionObj; + return pOptionObj; } //++ ------------------------------------------------------------------------------------ -// Details: Validate the option or argument is the correct type. -// Type: Method. -// Args: vrTxt - (R) Text version the option or argument. -// veType - (R) The type of value to expect. -// Return: bool - True = Yes expected type present, False = no. -// Throws: None. +// Details: Validate the option or argument is the correct type. +// Type: Method. +// Args: vrTxt - (R) Text version the option or argument. +// veType - (R) The type of value to expect. +// Return: bool - True = Yes expected type present, False = no. +// Throws: None. //-- -bool CMICmdArgValListBase::IsExpectedCorrectType( const CMIUtilString & vrTxt, const ArgValType_e veType ) const +bool +CMICmdArgValListBase::IsExpectedCorrectType(const CMIUtilString &vrTxt, const ArgValType_e veType) const { - bool bValid = false; - switch( veType ) - { - case eArgValType_File: - bValid = CMICmdArgValFile().IsFilePath( vrTxt ); - break; - case eArgValType_Consume: - bValid = CMICmdArgValConsume().IsOk(); - break; - case eArgValType_Number: - bValid = CMICmdArgValNumber().IsArgNumber( vrTxt ); - break; - case eArgValType_OptionLong: - bValid = CMICmdArgValOptionLong().IsArgLongOption( vrTxt ); - break; - case eArgValType_OptionShort: - bValid = CMICmdArgValOptionShort().IsArgShortOption( vrTxt ); - break; - case eArgValType_String: - bValid = CMICmdArgValString().IsStringArg( vrTxt ); - break; - case eArgValType_StringQuoted: - bValid = CMICmdArgValString( true, false, false ).IsStringArg( vrTxt ); - break; - case eArgValType_StringQuotedNumber: - bValid = CMICmdArgValString( true, true, false ).IsStringArg( vrTxt ); - break; - case eArgValType_StringQuotedNumberPath: - bValid = CMICmdArgValString( true, true, true ).IsStringArg( vrTxt ); - break; - case eArgValType_StringAnything: - bValid = CMICmdArgValString( true ).IsStringArg( vrTxt ); - break; - case eArgValType_ThreadGrp: - bValid = CMICmdArgValThreadGrp().IsArgThreadGrp( vrTxt ); - break; - default: - return false; - } + bool bValid = false; + switch (veType) + { + case eArgValType_File: + bValid = CMICmdArgValFile().IsFilePath(vrTxt); + break; + case eArgValType_Consume: + bValid = CMICmdArgValConsume().IsOk(); + break; + case eArgValType_Number: + bValid = CMICmdArgValNumber().IsArgNumber(vrTxt); + break; + case eArgValType_OptionLong: + bValid = CMICmdArgValOptionLong().IsArgLongOption(vrTxt); + break; + case eArgValType_OptionShort: + bValid = CMICmdArgValOptionShort().IsArgShortOption(vrTxt); + break; + case eArgValType_String: + bValid = CMICmdArgValString().IsStringArg(vrTxt); + break; + case eArgValType_StringQuoted: + bValid = CMICmdArgValString(true, false, false).IsStringArg(vrTxt); + break; + case eArgValType_StringQuotedNumber: + bValid = CMICmdArgValString(true, true, false).IsStringArg(vrTxt); + break; + case eArgValType_StringQuotedNumberPath: + bValid = CMICmdArgValString(true, true, true).IsStringArg(vrTxt); + break; + case eArgValType_StringAnything: + bValid = CMICmdArgValString(true).IsStringArg(vrTxt); + break; + case eArgValType_ThreadGrp: + bValid = CMICmdArgValThreadGrp().IsArgThreadGrp(vrTxt); + break; + default: + return false; + } - return bValid; + return bValid; } diff --git a/tools/lldb-mi/MICmdArgValListBase.h b/tools/lldb-mi/MICmdArgValListBase.h index 2798efa19a48..0e56f6dac021 100644 --- a/tools/lldb-mi/MICmdArgValListBase.h +++ b/tools/lldb-mi/MICmdArgValListBase.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValListBase.h +// File: MICmdArgValListBase.h // -// Overview: CMICmdArgValListBase interface. +// Overview: CMICmdArgValListBase interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -31,73 +31,74 @@ class CMICmdArgContext; //++ ============================================================================ -// Details: MI common code class. Command argument with addition options class. -// For example --recurse 1 2 4 [group ...]. Arguments object that -// require a list of options associated with them derive from the -// CMICmdArgValListBase class. Additional options are also extracted from -// the command arguments text string. -// An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching -// options and so extract a values from it . -// The CMICmdArgValBase objects are added to the derived argument class's -// container. The option arguments belong to that derived class and will -// be deleted that object goes out of scope. -// Based on the Interpreter pattern. -// Gotchas: None. -// Authors: Illya Rudkin 16/04/2014. -// Changes: None. +// Details: MI common code class. Command argument with addition options class. +// For example --recurse 1 2 4 [group ...]. Arguments object that +// require a list of options associated with them derive from the +// CMICmdArgValListBase class. Additional options are also extracted from +// the command arguments text string. +// An argument knows what type of argument it is and how it is to +// interpret the options (context) string to find and validate a matching +// options and so extract a values from it . +// The CMICmdArgValBase objects are added to the derived argument class's +// container. The option arguments belong to that derived class and will +// be deleted that object goes out of scope. +// Based on the Interpreter pattern. +// Gotchas: None. +// Authors: Illya Rudkin 16/04/2014. +// Changes: None. //-- -class CMICmdArgValListBase : public CMICmdArgValBaseTemplate< std::vector< CMICmdArgValBase * > > +class CMICmdArgValListBase : public CMICmdArgValBaseTemplate> { -// Typedef: -public: - typedef std::vector< CMICmdArgValBase * > VecArgObjPtr_t; + // Typedef: + public: + typedef std::vector VecArgObjPtr_t; -// Enums: -public: - //++ --------------------------------------------------------------------------------- - // Details: CMICmdArgValListBase needs to know what type of argument to look for in - // the command options text. It also needs to create argument objects of - // a specific type. - //-- - enum ArgValType_e - { - eArgValType_File = 0, - eArgValType_Consume, - eArgValType_Number, - eArgValType_OptionLong, - eArgValType_OptionShort, - eArgValType_String, - eArgValType_StringQuoted, - eArgValType_StringQuotedNumber, - eArgValType_StringQuotedNumberPath, - eArgValType_StringAnything, // Accept any words for a string 'type' even if they look like --longOptions for example - eArgValType_ThreadGrp, - eArgValType_count, // Always the last one - eArgValType_invalid - }; + // Enums: + public: + //++ --------------------------------------------------------------------------------- + // Details: CMICmdArgValListBase needs to know what type of argument to look for in + // the command options text. It also needs to create argument objects of + // a specific type. + //-- + enum ArgValType_e + { + eArgValType_File = 0, + eArgValType_Consume, + eArgValType_Number, + eArgValType_OptionLong, + eArgValType_OptionShort, + eArgValType_String, + eArgValType_StringQuoted, + eArgValType_StringQuotedNumber, + eArgValType_StringQuotedNumberPath, + eArgValType_StringAnything, // Accept any words for a string 'type' even if they look like --longOptions for example + eArgValType_ThreadGrp, + eArgValType_count, // Always the last one + eArgValType_invalid + }; -// Methods: -public: - /* ctor */ CMICmdArgValListBase( void ); - /* ctor */ CMICmdArgValListBase( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ); - /* ctor */ CMICmdArgValListBase( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType ); + // Methods: + public: + /* ctor */ CMICmdArgValListBase(void); + /* ctor */ CMICmdArgValListBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); + /* ctor */ CMICmdArgValListBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, + const ArgValType_e veType); -// Overridden: -public: - // From CMICmdArgValBase - /* dtor */ virtual ~CMICmdArgValListBase( void ); + // Overridden: + public: + // From CMICmdArgValBase + /* dtor */ virtual ~CMICmdArgValListBase(void); -// Methods: -protected: - bool IsExpectedCorrectType( const CMIUtilString & vrTxt, const ArgValType_e veType ) const; - CMICmdArgValBase * CreationObj( const CMIUtilString & vrTxt, const ArgValType_e veType ) const; - -// Attributes: -protected: - ArgValType_e m_eArgType; + // Methods: + protected: + bool IsExpectedCorrectType(const CMIUtilString &vrTxt, const ArgValType_e veType) const; + CMICmdArgValBase *CreationObj(const CMIUtilString &vrTxt, const ArgValType_e veType) const; -// Methods: -private: - void Destroy( void ); + // Attributes: + protected: + ArgValType_e m_eArgType; + + // Methods: + private: + void Destroy(void); }; diff --git a/tools/lldb-mi/MICmdArgValListOfN.cpp b/tools/lldb-mi/MICmdArgValListOfN.cpp index 246fa2c9445d..9a4711485f0b 100644 --- a/tools/lldb-mi/MICmdArgValListOfN.cpp +++ b/tools/lldb-mi/MICmdArgValListOfN.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValListOfN.cpp +// File: MICmdArgValListOfN.cpp // -// Overview: CMICmdArgValListOfN implementation. +// Overview: CMICmdArgValListOfN implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -30,160 +30,159 @@ #include "MICmdArgValThreadGrp.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValListOfN constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValListOfN constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValListOfN::CMICmdArgValListOfN( void ) +CMICmdArgValListOfN::CMICmdArgValListOfN(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValListOfN constructor. -// Type: Method. -// Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// veType - (R) The type of argument to look for and create argument object of a certain type. -// Return: None. -// Throws: None. +// Details: CMICmdArgValListOfN constructor. +// Type: Method. +// Args: vrArgName - (R) Argument's name to search by. +// vbMandatory - (R) True = Yes must be present, false = optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// veType - (R) The type of argument to look for and create argument object of a certain type. +// Return: None. +// Throws: None. //-- -CMICmdArgValListOfN::CMICmdArgValListOfN( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType ) -: CMICmdArgValListBase( vrArgName, vbMandatory, vbHandleByCmd, veType ) +CMICmdArgValListOfN::CMICmdArgValListOfN(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, + const ArgValType_e veType) + : CMICmdArgValListBase(vrArgName, vbMandatory, vbHandleByCmd, veType) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValListOfN destructor. -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValListOfN destructor. +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValListOfN::~CMICmdArgValListOfN( void ) +CMICmdArgValListOfN::~CMICmdArgValListOfN(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the list of -// arguments based on the argument object type to look for. -// Type: Overridden. -// Args: vwArgContext - (RW) The command's argument options string. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Parse the command's argument options string and try to extract the list of +// arguments based on the argument object type to look for. +// Type: Overridden. +// Args: vwArgContext - (RW) The command's argument options string. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgValListOfN::Validate( CMICmdArgContext & vwArgContext ) +bool +CMICmdArgValListOfN::Validate(CMICmdArgContext &vwArgContext) { - if( m_eArgType >= eArgValType_count ) - { - m_eArgType = eArgValType_invalid; - return MIstatus::failure; - } - - if( vwArgContext.IsEmpty() ) - return MIstatus::success; - - const CMIUtilString & rArg( vwArgContext.GetArgsLeftToParse() ); - if( IsListOfN( rArg ) && CreateList( rArg ) ) - { - m_bFound = true; - m_bValid = true; - vwArgContext.RemoveArg( rArg ); - return MIstatus::success; - } - else - return MIstatus::failure; + if (m_eArgType >= eArgValType_count) + { + m_eArgType = eArgValType_invalid; + return MIstatus::failure; + } + + if (vwArgContext.IsEmpty()) + return MIstatus::success; + + const CMIUtilString &rArg(vwArgContext.GetArgsLeftToParse()); + if (IsListOfN(rArg) && CreateList(rArg)) + { + m_bFound = true; + m_bValid = true; + vwArgContext.RemoveArg(rArg); + return MIstatus::success; + } + else + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Create list of argument objects each holding a value extract from the command -// options line. -// Type: Method. -// Args: vrTxt - (R) Some options text. -// Return: bool - True = yes valid arg, false = no. -// Throws: None. +// Details: Create list of argument objects each holding a value extract from the command +// options line. +// Type: Method. +// Args: vrTxt - (R) Some options text. +// Return: bool - True = yes valid arg, false = no. +// Throws: None. //-- -bool CMICmdArgValListOfN::CreateList( const CMIUtilString & vrTxt ) +bool +CMICmdArgValListOfN::CreateList(const CMIUtilString &vrTxt) { - CMIUtilString::VecString_t vecOptions; - if( (m_eArgType == eArgValType_StringQuoted) || - (m_eArgType == eArgValType_StringQuotedNumber) || - (m_eArgType == eArgValType_StringQuotedNumberPath) || - (m_eArgType == eArgValType_StringAnything) ) - { - if( vrTxt.SplitConsiderQuotes( " ", vecOptions ) == 0 ) - return MIstatus::failure; - } - else - if( vrTxt.Split( " ", vecOptions ) == 0 ) - return MIstatus::failure; - - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while( it != vecOptions.end() ) - { - const CMIUtilString & rOption = *it; - CMICmdArgValBase * pOption = CreationObj( rOption, m_eArgType ); - if( pOption != nullptr ) - m_argValue.push_back( pOption ); - else - return MIstatus::failure; - - // Next - ++it; - } - - return MIstatus::success; + CMIUtilString::VecString_t vecOptions; + if ((m_eArgType == eArgValType_StringQuoted) || (m_eArgType == eArgValType_StringQuotedNumber) || + (m_eArgType == eArgValType_StringQuotedNumberPath) || (m_eArgType == eArgValType_StringAnything)) + { + if (vrTxt.SplitConsiderQuotes(" ", vecOptions) == 0) + return MIstatus::failure; + } + else if (vrTxt.Split(" ", vecOptions) == 0) + return MIstatus::failure; + + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) + { + const CMIUtilString &rOption = *it; + CMICmdArgValBase *pOption = CreationObj(rOption, m_eArgType); + if (pOption != nullptr) + m_argValue.push_back(pOption); + else + return MIstatus::failure; + + // Next + ++it; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument. -// Type: Method. -// Args: vrTxt - (R) Some text. -// Return: bool - True = yes valid arg, false = no. -// Throws: None. +// Details: Examine the string and determine if it is a valid string type argument. +// Type: Method. +// Args: vrTxt - (R) Some text. +// Return: bool - True = yes valid arg, false = no. +// Throws: None. //-- -bool CMICmdArgValListOfN::IsListOfN( const CMIUtilString & vrTxt ) const +bool +CMICmdArgValListOfN::IsListOfN(const CMIUtilString &vrTxt) const { - CMIUtilString::VecString_t vecOptions; - if( (m_eArgType == eArgValType_StringQuoted) || - (m_eArgType == eArgValType_StringQuotedNumber) || - (m_eArgType == eArgValType_StringQuotedNumberPath) || - (m_eArgType == eArgValType_StringAnything) ) - { - if( vrTxt.SplitConsiderQuotes( " ", vecOptions ) == 0 ) - return false; - } - else - if( vrTxt.Split( " ", vecOptions ) == 0 ) - return false; - - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while( it != vecOptions.end() ) - { - const CMIUtilString & rOption = *it; - if( !IsExpectedCorrectType( rOption, m_eArgType ) ) - break; - - // Next - ++it; - } - - return true; + CMIUtilString::VecString_t vecOptions; + if ((m_eArgType == eArgValType_StringQuoted) || (m_eArgType == eArgValType_StringQuotedNumber) || + (m_eArgType == eArgValType_StringQuotedNumberPath) || (m_eArgType == eArgValType_StringAnything)) + { + if (vrTxt.SplitConsiderQuotes(" ", vecOptions) == 0) + return false; + } + else if (vrTxt.Split(" ", vecOptions) == 0) + return false; + + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) + { + const CMIUtilString &rOption = *it; + if (!IsExpectedCorrectType(rOption, m_eArgType)) + break; + + // Next + ++it; + } + + return true; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the list of CMICmdArgValBase derived option objects found following -// *this long option argument. For example "list-thread-groups [ --recurse 1 ]" -// where 1 is the list of expected option to follow. -// Type: Method. -// Args: None. -// Return: CMICmdArgValListBase::VecArgObjPtr_t & - List of options. -// Throws: None. +// Details: Retrieve the list of CMICmdArgValBase derived option objects found following +// *this long option argument. For example "list-thread-groups [ --recurse 1 ]" +// where 1 is the list of expected option to follow. +// Type: Method. +// Args: None. +// Return: CMICmdArgValListBase::VecArgObjPtr_t & - List of options. +// Throws: None. //-- -const CMICmdArgValListBase::VecArgObjPtr_t & CMICmdArgValListOfN::GetExpectedOptions( void ) const +const CMICmdArgValListBase::VecArgObjPtr_t & +CMICmdArgValListOfN::GetExpectedOptions(void) const { - return m_argValue; + return m_argValue; } diff --git a/tools/lldb-mi/MICmdArgValListOfN.h b/tools/lldb-mi/MICmdArgValListOfN.h index 0fe5d2f4f831..48ee77f79e72 100644 --- a/tools/lldb-mi/MICmdArgValListOfN.h +++ b/tools/lldb-mi/MICmdArgValListOfN.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValListOfN.h +// File: MICmdArgValListOfN.h // -// Overview: CMICmdArgValListOfN interface. +// Overview: CMICmdArgValListOfN interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -31,68 +31,69 @@ class CMICmdArgContext; //++ ============================================================================ -// Details: MI common code class. Command argument class. Arguments object -// needing specialization derived from the CMICmdArgValBase class. -// An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching -// argument and so extract a value from it . -// The CMICmdArgValBase objects added to *this ListOfN container belong -// to this container and will be deleted when *this object goes out of -// scope. -// To parse arguments like 'thread-id ...' i.e. 1 10 12 13 ... -// If vbMandatory argument is true it takes on the (...)+ specification -// otherwise assumed to be (...)* specification. -// Based on the Interpreter pattern. -// Gotchas: None. -// Authors: Illya Rudkin 16/04/2014. -// Changes: None. +// Details: MI common code class. Command argument class. Arguments object +// needing specialization derived from the CMICmdArgValBase class. +// An argument knows what type of argument it is and how it is to +// interpret the options (context) string to find and validate a matching +// argument and so extract a value from it . +// The CMICmdArgValBase objects added to *this ListOfN container belong +// to this container and will be deleted when *this object goes out of +// scope. +// To parse arguments like 'thread-id ...' i.e. 1 10 12 13 ... +// If vbMandatory argument is true it takes on the (...)+ specification +// otherwise assumed to be (...)* specification. +// Based on the Interpreter pattern. +// Gotchas: None. +// Authors: Illya Rudkin 16/04/2014. +// Changes: None. //-- class CMICmdArgValListOfN : public CMICmdArgValListBase { -// Methods: -public: - /* ctor */ CMICmdArgValListOfN( void ); - /* ctor */ CMICmdArgValListOfN( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType ); - // - const VecArgObjPtr_t & GetExpectedOptions( void ) const; - template< class T1, typename T2 > - bool GetExpectedOption( T2 & vrwValue ) const; + // Methods: + public: + /* ctor */ CMICmdArgValListOfN(void); + /* ctor */ CMICmdArgValListOfN(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, + const ArgValType_e veType); + // + const VecArgObjPtr_t &GetExpectedOptions(void) const; + template bool GetExpectedOption(T2 &vrwValue) const; -// Overridden: -public: - // From CMICmdArgValBase - /* dtor */ virtual ~CMICmdArgValListOfN( void ); - // From CMICmdArgSet::IArg - virtual bool Validate( CMICmdArgContext & vArgContext ); + // Overridden: + public: + // From CMICmdArgValBase + /* dtor */ virtual ~CMICmdArgValListOfN(void); + // From CMICmdArgSet::IArg + virtual bool Validate(CMICmdArgContext &vArgContext); -// Methods: -private: - bool IsListOfN( const CMIUtilString & vrTxt ) const; - bool CreateList( const CMIUtilString & vrTxt ); + // Methods: + private: + bool IsListOfN(const CMIUtilString &vrTxt) const; + bool CreateList(const CMIUtilString &vrTxt); }; //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the first argument or option value from the list of 1 or more options -// parsed from the command's options string. -// Type: Template method. -// Args: vrwValue - (W) Templated type return value. -// T1 - The argument value's class type of the data hold in the list of options. -// T2 - The type pf the variable which holds the value wanted. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. List of object was empty. -// Throws: None. +// Details: Retrieve the first argument or option value from the list of 1 or more options +// parsed from the command's options string. +// Type: Template method. +// Args: vrwValue - (W) Templated type return value. +// T1 - The argument value's class type of the data hold in the list of options. +// T2 - The type pf the variable which holds the value wanted. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. List of object was empty. +// Throws: None. //-- -template< class T1, typename T2 > -bool CMICmdArgValListOfN::GetExpectedOption( T2 & vrwValue ) const +template +bool +CMICmdArgValListOfN::GetExpectedOption(T2 &vrwValue) const { - const VecArgObjPtr_t & rVecOptions( GetExpectedOptions() ); - VecArgObjPtr_t::const_iterator it2 = rVecOptions.begin(); - if( it2 != rVecOptions.end() ) - { - const T1 * pOption = static_cast< T1 * >( *it2 ); - vrwValue = pOption->GetValue(); - return MIstatus::success; - } + const VecArgObjPtr_t &rVecOptions(GetExpectedOptions()); + VecArgObjPtr_t::const_iterator it2 = rVecOptions.begin(); + if (it2 != rVecOptions.end()) + { + const T1 *pOption = static_cast(*it2); + vrwValue = pOption->GetValue(); + return MIstatus::success; + } - return MIstatus::failure; + return MIstatus::failure; } diff --git a/tools/lldb-mi/MICmdArgValNumber.cpp b/tools/lldb-mi/MICmdArgValNumber.cpp index 18bdccdc9ac5..8b1878df028b 100644 --- a/tools/lldb-mi/MICmdArgValNumber.cpp +++ b/tools/lldb-mi/MICmdArgValNumber.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValNumber.cpp +// File: MICmdArgValNumber.cpp // -// Overview: CMICmdArgValNumber implementation. +// Overview: CMICmdArgValNumber implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -24,144 +24,147 @@ #include "MICmdArgContext.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValNumber constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValNumber constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValNumber::CMICmdArgValNumber( void ) -: m_nNumber( 0 ) +CMICmdArgValNumber::CMICmdArgValNumber(void) + : m_nNumber(0) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValNumber constructor. -// Type: Method. -// Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// Return: None. -// Throws: None. +// Details: CMICmdArgValNumber constructor. +// Type: Method. +// Args: vrArgName - (R) Argument's name to search by. +// vbMandatory - (R) True = Yes must be present, false = optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// Return: None. +// Throws: None. //-- -CMICmdArgValNumber::CMICmdArgValNumber( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ) -: CMICmdArgValBaseTemplate( vrArgName, vbMandatory, vbHandleByCmd ) -, m_nNumber( 0 ) +CMICmdArgValNumber::CMICmdArgValNumber(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) + , m_nNumber(0) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValNumber destructor. -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValNumber destructor. +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValNumber::~CMICmdArgValNumber( void ) +CMICmdArgValNumber::~CMICmdArgValNumber(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the value *this -// argument is looking for. -// Type: Overridden. -// Args: vwArgContext - (RW) The command's argument options string. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Parse the command's argument options string and try to extract the value *this +// argument is looking for. +// Type: Overridden. +// Args: vwArgContext - (RW) The command's argument options string. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgValNumber::Validate( CMICmdArgContext & vwArgContext ) +bool +CMICmdArgValNumber::Validate(CMICmdArgContext &vwArgContext) { - if( vwArgContext.IsEmpty() ) - return MIstatus::success; - - if( vwArgContext.GetNumberArgsPresent() == 1 ) - { - const CMIUtilString & rArg( vwArgContext.GetArgsLeftToParse() ); - if( IsArgNumber( rArg ) && ExtractNumber( rArg ) ) - { - m_bFound = true; - m_bValid = true; - m_argValue = GetNumber(); - vwArgContext.RemoveArg( rArg ); - return MIstatus::success; - } - else - return MIstatus::failure; - } - - // More than one option... - const CMIUtilString::VecString_t vecOptions( vwArgContext.GetArgs() ); - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while( it != vecOptions.end() ) - { - const CMIUtilString & rArg( *it ); - if( IsArgNumber( rArg ) && ExtractNumber( rArg ) ) - { - m_bFound = true; - - if( vwArgContext.RemoveArg( rArg ) ) - { - m_bValid = true; - m_argValue = GetNumber(); - return MIstatus::success; - } - else - return MIstatus::failure; - } - - // Next - ++it; - } - - return MIstatus::failure; + if (vwArgContext.IsEmpty()) + return MIstatus::success; + + if (vwArgContext.GetNumberArgsPresent() == 1) + { + const CMIUtilString &rArg(vwArgContext.GetArgsLeftToParse()); + if (IsArgNumber(rArg) && ExtractNumber(rArg)) + { + m_bFound = true; + m_bValid = true; + m_argValue = GetNumber(); + vwArgContext.RemoveArg(rArg); + return MIstatus::success; + } + else + return MIstatus::failure; + } + + // More than one option... + const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) + { + const CMIUtilString &rArg(*it); + if (IsArgNumber(rArg) && ExtractNumber(rArg)) + { + m_bFound = true; + + if (vwArgContext.RemoveArg(rArg)) + { + m_bValid = true; + m_argValue = GetNumber(); + return MIstatus::success; + } + else + return MIstatus::failure; + } + + // Next + ++it; + } + + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument. -// Type: Method. -// Args: vrTxt - (R) Some text. -// Return: bool - True = yes valid arg, false = no. -// Throws: None. +// Details: Examine the string and determine if it is a valid string type argument. +// Type: Method. +// Args: vrTxt - (R) Some text. +// Return: bool - True = yes valid arg, false = no. +// Throws: None. //-- -bool CMICmdArgValNumber::IsArgNumber( const CMIUtilString & vrTxt ) const +bool +CMICmdArgValNumber::IsArgNumber(const CMIUtilString &vrTxt) const { - // Look for --someLongOption - if( std::string::npos != vrTxt.find( "--" ) ) - return false; - - return vrTxt.IsNumber(); + // Look for --someLongOption + if (std::string::npos != vrTxt.find("--")) + return false; + + return vrTxt.IsNumber(); } //++ ------------------------------------------------------------------------------------ -// Details: Extract the thread group number from the thread group argument. -// Type: Method. -// Args: vrTxt - (R) Some text. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Extract the thread group number from the thread group argument. +// Type: Method. +// Args: vrTxt - (R) Some text. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgValNumber::ExtractNumber( const CMIUtilString & vrTxt ) +bool +CMICmdArgValNumber::ExtractNumber(const CMIUtilString &vrTxt) { - MIint64 nNumber = 0; - bool bOk = vrTxt.ExtractNumber( nNumber ); - if( bOk ) - { - m_nNumber = static_cast< MIint >( nNumber ); - } - - return bOk; + MIint64 nNumber = 0; + bool bOk = vrTxt.ExtractNumber(nNumber); + if (bOk) + { + m_nNumber = static_cast(nNumber); + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the thread group ID found in the argument. -// Type: Method. -// Args: None. -// Return: MIuint - Thread group ID. -// Throws: None. +// Details: Retrieve the thread group ID found in the argument. +// Type: Method. +// Args: None. +// Return: MIuint - Thread group ID. +// Throws: None. //-- -MIint64 CMICmdArgValNumber::GetNumber( void ) const +MIint64 +CMICmdArgValNumber::GetNumber(void) const { - return m_nNumber; + return m_nNumber; } - diff --git a/tools/lldb-mi/MICmdArgValNumber.h b/tools/lldb-mi/MICmdArgValNumber.h index 219b040a257d..1a782e1af388 100644 --- a/tools/lldb-mi/MICmdArgValNumber.h +++ b/tools/lldb-mi/MICmdArgValNumber.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValNumber.h +// File: MICmdArgValNumber.h // -// Overview: CMICmdArgValNumber interface. +// Overview: CMICmdArgValNumber interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -28,38 +28,38 @@ class CMICmdArgContext; //++ ============================================================================ -// Details: MI common code class. Command argument class. Arguments object -// needing specialization derived from the CMICmdArgValBase class. -// An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching -// argument and so extract a value from it . -// Based on the Interpreter pattern. -// Gotchas: None. -// Authors: Illya Rudkin 14/04/2014. -// Changes: None. +// Details: MI common code class. Command argument class. Arguments object +// needing specialization derived from the CMICmdArgValBase class. +// An argument knows what type of argument it is and how it is to +// interpret the options (context) string to find and validate a matching +// argument and so extract a value from it . +// Based on the Interpreter pattern. +// Gotchas: None. +// Authors: Illya Rudkin 14/04/2014. +// Changes: None. //-- -class CMICmdArgValNumber : public CMICmdArgValBaseTemplate< MIint64 > +class CMICmdArgValNumber : public CMICmdArgValBaseTemplate { -// Methods: -public: - /* ctor */ CMICmdArgValNumber( void ); - /* ctor */ CMICmdArgValNumber( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ); - // - bool IsArgNumber( const CMIUtilString & vrTxt ) const; - -// Overridden: -public: - // From CMICmdArgValBase - /* dtor */ virtual ~CMICmdArgValNumber( void ); - // From CMICmdArgSet::IArg - virtual bool Validate( CMICmdArgContext & vwArgContext ); + // Methods: + public: + /* ctor */ CMICmdArgValNumber(void); + /* ctor */ CMICmdArgValNumber(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); + // + bool IsArgNumber(const CMIUtilString &vrTxt) const; -// Methods: -private: - bool ExtractNumber( const CMIUtilString & vrTxt ); - MIint64 GetNumber( void ) const; + // Overridden: + public: + // From CMICmdArgValBase + /* dtor */ virtual ~CMICmdArgValNumber(void); + // From CMICmdArgSet::IArg + virtual bool Validate(CMICmdArgContext &vwArgContext); -// Attributes: -private: - MIint64 m_nNumber; + // Methods: + private: + bool ExtractNumber(const CMIUtilString &vrTxt); + MIint64 GetNumber(void) const; + + // Attributes: + private: + MIint64 m_nNumber; }; diff --git a/tools/lldb-mi/MICmdArgValOptionLong.cpp b/tools/lldb-mi/MICmdArgValOptionLong.cpp index 6c87984ba811..0c29982e2634 100644 --- a/tools/lldb-mi/MICmdArgValOptionLong.cpp +++ b/tools/lldb-mi/MICmdArgValOptionLong.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValOptionLong.cpp +// File: MICmdArgValOptionLong.cpp // -// Overview: CMICmdArgValOptionLong implementation. +// Overview: CMICmdArgValOptionLong implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -24,296 +24,302 @@ #include "MICmdArgContext.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValOptionLong constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValOptionLong constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValOptionLong::CMICmdArgValOptionLong( void ) -: m_nExpectingNOptions( 0 ) -, m_eExpectingOptionType( eArgValType_invalid ) +CMICmdArgValOptionLong::CMICmdArgValOptionLong(void) + : m_nExpectingNOptions(0) + , m_eExpectingOptionType(eArgValType_invalid) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValOptionLong constructor. -// Type: Method. -// Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// Return: None. -// Throws: None. +// Details: CMICmdArgValOptionLong constructor. +// Type: Method. +// Args: vrArgName - (R) Argument's name to search by. +// vbMandatory - (R) True = Yes must be present, false = optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// Return: None. +// Throws: None. //-- -CMICmdArgValOptionLong::CMICmdArgValOptionLong( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ) -: CMICmdArgValListBase( vrArgName, vbMandatory, vbHandleByCmd ) -, m_nExpectingNOptions( 0 ) -, m_eExpectingOptionType( eArgValType_invalid ) +CMICmdArgValOptionLong::CMICmdArgValOptionLong(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) + : CMICmdArgValListBase(vrArgName, vbMandatory, vbHandleByCmd) + , m_nExpectingNOptions(0) + , m_eExpectingOptionType(eArgValType_invalid) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValOptionLong constructor. -// Type: Method. -// Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// veType - (R) The type of argument to look for and create argument object of a certain type. -// vnExpectingNOptions - (R) The number of options expected to read following *this argument. -// Return: None. -// Throws: None. +// Details: CMICmdArgValOptionLong constructor. +// Type: Method. +// Args: vrArgName - (R) Argument's name to search by. +// vbMandatory - (R) True = Yes must be present, false = optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// veType - (R) The type of argument to look for and create argument object of a certain type. +// vnExpectingNOptions - (R) The number of options expected to read following *this argument. +// Return: None. +// Throws: None. //-- -CMICmdArgValOptionLong::CMICmdArgValOptionLong( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType, const MIuint vnExpectingNOptions ) -: CMICmdArgValListBase( vrArgName, vbMandatory, vbHandleByCmd ) -, m_nExpectingNOptions( vnExpectingNOptions ) -, m_eExpectingOptionType( veType ) +CMICmdArgValOptionLong::CMICmdArgValOptionLong(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, + const ArgValType_e veType, const MIuint vnExpectingNOptions) + : CMICmdArgValListBase(vrArgName, vbMandatory, vbHandleByCmd) + , m_nExpectingNOptions(vnExpectingNOptions) + , m_eExpectingOptionType(veType) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValOptionLong destructor. -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValOptionLong destructor. +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValOptionLong::~CMICmdArgValOptionLong( void ) +CMICmdArgValOptionLong::~CMICmdArgValOptionLong(void) { - // Tidy up - Destroy(); + // Tidy up + Destroy(); } //++ ------------------------------------------------------------------------------------ -// Details: Tear down resources used by *this object. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: Tear down resources used by *this object. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMICmdArgValOptionLong::Destroy( void ) +void +CMICmdArgValOptionLong::Destroy(void) { - // Tidy up - VecArgObjPtr_t::const_iterator it = m_vecArgsExpected.begin(); - while( it != m_vecArgsExpected.end() ) - { - CMICmdArgValBase * pOptionObj = *it; - delete pOptionObj; - - // Next - ++it; - } - m_vecArgsExpected.clear(); + // Tidy up + VecArgObjPtr_t::const_iterator it = m_vecArgsExpected.begin(); + while (it != m_vecArgsExpected.end()) + { + CMICmdArgValBase *pOptionObj = *it; + delete pOptionObj; + + // Next + ++it; + } + m_vecArgsExpected.clear(); } //++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the long -// argument *this argument type is looking for. -// Type: Overridden. -// Args: vwArgContext - (RW) The command's argument options string. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Parse the command's argument options string and try to extract the long +// argument *this argument type is looking for. +// Type: Overridden. +// Args: vwArgContext - (RW) The command's argument options string. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgValOptionLong::Validate( CMICmdArgContext & vwArgContext ) +bool +CMICmdArgValOptionLong::Validate(CMICmdArgContext &vwArgContext) { - if( vwArgContext.IsEmpty() ) - return MIstatus::success; - - if( vwArgContext.GetNumberArgsPresent() == 1 ) - { - const CMIUtilString & rArg( vwArgContext.GetArgsLeftToParse() ); - if( IsArgLongOption( rArg ) && ArgNameMatch( rArg ) ) - { - m_bFound = true; - - if( !vwArgContext.RemoveArg( rArg ) ) - return MIstatus::failure; - - if( m_nExpectingNOptions == 0 ) - { - m_bValid = true; - return MIstatus::success; - } - - m_bIsMissingOptions = true; - return MIstatus::failure; - } - else - return MIstatus::failure; - } - - // More than one option... - MIuint nArgIndex = 0; - const CMIUtilString::VecString_t vecOptions( vwArgContext.GetArgs() ); - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while( it != vecOptions.end() ) - { - const CMIUtilString & rArg( *it ); - if( IsArgOptionCorrect( rArg ) && ArgNameMatch( rArg ) ) - { - m_bFound = true; - - if( !vwArgContext.RemoveArg( rArg ) ) - return MIstatus::failure; - - if( m_nExpectingNOptions != 0 ) - { - if( ExtractExpectedOptions( vwArgContext, nArgIndex ) ) - { - m_bValid = true; - return MIstatus::success; - } - - m_bIsMissingOptions = true; - return MIstatus::failure; - } - else - { - m_bValid = true; - return MIstatus::success; - } - } - - // Next - ++it; - ++nArgIndex; - } - - return MIstatus::failure; + if (vwArgContext.IsEmpty()) + return MIstatus::success; + + if (vwArgContext.GetNumberArgsPresent() == 1) + { + const CMIUtilString &rArg(vwArgContext.GetArgsLeftToParse()); + if (IsArgLongOption(rArg) && ArgNameMatch(rArg)) + { + m_bFound = true; + + if (!vwArgContext.RemoveArg(rArg)) + return MIstatus::failure; + + if (m_nExpectingNOptions == 0) + { + m_bValid = true; + return MIstatus::success; + } + + m_bIsMissingOptions = true; + return MIstatus::failure; + } + else + return MIstatus::failure; + } + + // More than one option... + MIuint nArgIndex = 0; + const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) + { + const CMIUtilString &rArg(*it); + if (IsArgOptionCorrect(rArg) && ArgNameMatch(rArg)) + { + m_bFound = true; + + if (!vwArgContext.RemoveArg(rArg)) + return MIstatus::failure; + + if (m_nExpectingNOptions != 0) + { + if (ExtractExpectedOptions(vwArgContext, nArgIndex)) + { + m_bValid = true; + return MIstatus::success; + } + + m_bIsMissingOptions = true; + return MIstatus::failure; + } + else + { + m_bValid = true; + return MIstatus::success; + } + } + + // Next + ++it; + ++nArgIndex; + } + + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Parse the text following *this argument and extract the options the values of -// CMICmdArgValListBase::m_eArgType forming argument objects for each of those -// options extracted. -// Type: Method. -// Args: vrwTxt - (RW) The command's argument options string. -// nArgIndex - (R) The Nth arg position in argument context from the left. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Parse the text following *this argument and extract the options the values of +// CMICmdArgValListBase::m_eArgType forming argument objects for each of those +// options extracted. +// Type: Method. +// Args: vrwTxt - (RW) The command's argument options string. +// nArgIndex - (R) The Nth arg position in argument context from the left. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgValOptionLong::ExtractExpectedOptions( CMICmdArgContext & vrwTxt, const MIuint nArgIndex ) +bool +CMICmdArgValOptionLong::ExtractExpectedOptions(CMICmdArgContext &vrwTxt, const MIuint nArgIndex) { - CMIUtilString::VecString_t vecOptions; - MIuint nOptionsPresent = 0; - if( (m_eExpectingOptionType != eArgValType_StringQuoted) && - (m_eExpectingOptionType != eArgValType_StringQuotedNumber) && - (m_eExpectingOptionType != eArgValType_StringQuotedNumberPath) ) - nOptionsPresent = vrwTxt.GetArgsLeftToParse().Split( " ", vecOptions ); - else - nOptionsPresent = vrwTxt.GetArgsLeftToParse().SplitConsiderQuotes( " ", vecOptions ); - if( nOptionsPresent == 0 ) - return MIstatus::failure; - - MIuint nArgIndexCnt = 0; - MIuint nTypeCnt = 0; - MIuint nTypeCnt2 = 0; - MIuint nFoundNOptionsCnt = 0; - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while( it != vecOptions.end() ) - { - // Move to the Nth argument position from left before do validation/checking - if( nArgIndexCnt++ == nArgIndex ) - { - nTypeCnt++; - const CMIUtilString & rOption( *it ); - if( IsExpectedCorrectType( rOption, m_eExpectingOptionType ) ) - { - nTypeCnt2++; - CMICmdArgValBase * pOptionObj = CreationObj( rOption, m_eExpectingOptionType ); - if( (pOptionObj != nullptr) && vrwTxt.RemoveArgAtPos( rOption, nArgIndex ) ) - { - nFoundNOptionsCnt++; - m_vecArgsExpected.push_back( pOptionObj ); - } - } - - // Is the sequence 'options' of same type broken. Expecting the same type until the - // next argument. - if( nTypeCnt != nTypeCnt2 ) - return MIstatus::failure; - - if( nFoundNOptionsCnt == m_nExpectingNOptions ) - return MIstatus::success; - } - - // Next - ++it; - } - if( nFoundNOptionsCnt != m_nExpectingNOptions ) - return MIstatus::failure; - - return MIstatus::success; + CMIUtilString::VecString_t vecOptions; + MIuint nOptionsPresent = 0; + if ((m_eExpectingOptionType != eArgValType_StringQuoted) && (m_eExpectingOptionType != eArgValType_StringQuotedNumber) && + (m_eExpectingOptionType != eArgValType_StringQuotedNumberPath)) + nOptionsPresent = vrwTxt.GetArgsLeftToParse().Split(" ", vecOptions); + else + nOptionsPresent = vrwTxt.GetArgsLeftToParse().SplitConsiderQuotes(" ", vecOptions); + if (nOptionsPresent == 0) + return MIstatus::failure; + + MIuint nArgIndexCnt = 0; + MIuint nTypeCnt = 0; + MIuint nTypeCnt2 = 0; + MIuint nFoundNOptionsCnt = 0; + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) + { + // Move to the Nth argument position from left before do validation/checking + if (nArgIndexCnt++ == nArgIndex) + { + nTypeCnt++; + const CMIUtilString &rOption(*it); + if (IsExpectedCorrectType(rOption, m_eExpectingOptionType)) + { + nTypeCnt2++; + CMICmdArgValBase *pOptionObj = CreationObj(rOption, m_eExpectingOptionType); + if ((pOptionObj != nullptr) && vrwTxt.RemoveArgAtPos(rOption, nArgIndex)) + { + nFoundNOptionsCnt++; + m_vecArgsExpected.push_back(pOptionObj); + } + } + + // Is the sequence 'options' of same type broken. Expecting the same type until the + // next argument. + if (nTypeCnt != nTypeCnt2) + return MIstatus::failure; + + if (nFoundNOptionsCnt == m_nExpectingNOptions) + return MIstatus::success; + } + + // Next + ++it; + } + if (nFoundNOptionsCnt != m_nExpectingNOptions) + return MIstatus::failure; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid long type option argument. -// Long type argument looks like --someLongOption. -// Type: Method. -// Args: vrTxt - (R) Some text. -// Return: bool - True = yes valid arg, false = no. -// Throws: None. +// Details: Examine the string and determine if it is a valid long type option argument. +// Long type argument looks like --someLongOption. +// Type: Method. +// Args: vrTxt - (R) Some text. +// Return: bool - True = yes valid arg, false = no. +// Throws: None. //-- -bool CMICmdArgValOptionLong::IsArgLongOption( const CMIUtilString & vrTxt ) const +bool +CMICmdArgValOptionLong::IsArgLongOption(const CMIUtilString &vrTxt) const { - const bool bHavePosSlash = (vrTxt.find_first_of( "/" ) != std::string::npos); - const bool bHaveBckSlash = (vrTxt.find_first_of( "\\" ) != std::string::npos); - if( bHavePosSlash || bHaveBckSlash ) - return false; - - const MIint nPos = vrTxt.find_first_of( "--" ); - if( nPos != 0 ) - return false; - - if( vrTxt.length() < 3 ) - return false; - - const CMIUtilString strArg = vrTxt.substr( 2 ).c_str(); - if( strArg.IsNumber() ) - return false; - - return true; + const bool bHavePosSlash = (vrTxt.find_first_of("/") != std::string::npos); + const bool bHaveBckSlash = (vrTxt.find_first_of("\\") != std::string::npos); + if (bHavePosSlash || bHaveBckSlash) + return false; + + const MIint nPos = vrTxt.find_first_of("--"); + if (nPos != 0) + return false; + + if (vrTxt.length() < 3) + return false; + + const CMIUtilString strArg = vrTxt.substr(2).c_str(); + if (strArg.IsNumber()) + return false; + + return true; } //++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid long type option argument. -// Long type argument looks like --someLongOption. -// Type: Overideable. -// Args: vrTxt - (R) Some text. -// Return: bool - True = yes valid arg, false = no. -// Throws: None. +// Details: Examine the string and determine if it is a valid long type option argument. +// Long type argument looks like --someLongOption. +// Type: Overideable. +// Args: vrTxt - (R) Some text. +// Return: bool - True = yes valid arg, false = no. +// Throws: None. //-- -bool CMICmdArgValOptionLong::IsArgOptionCorrect( const CMIUtilString & vrTxt ) const +bool +CMICmdArgValOptionLong::IsArgOptionCorrect(const CMIUtilString &vrTxt) const { - return IsArgLongOption( vrTxt ); + return IsArgLongOption(vrTxt); } //++ ------------------------------------------------------------------------------------ -// Details: Does the argument name of the argument being parsed ATM match the name of -// *this argument object. -// Type: Method. -// Args: vrTxt - (R) Some text. -// Return: bool - True = yes arg name matched, false = no. -// Throws: None. +// Details: Does the argument name of the argument being parsed ATM match the name of +// *this argument object. +// Type: Method. +// Args: vrTxt - (R) Some text. +// Return: bool - True = yes arg name matched, false = no. +// Throws: None. //-- -bool CMICmdArgValOptionLong::ArgNameMatch( const CMIUtilString & vrTxt ) const +bool +CMICmdArgValOptionLong::ArgNameMatch(const CMIUtilString &vrTxt) const { - const CMIUtilString strArg = vrTxt.substr( 2 ).c_str(); - return (strArg == GetName() ); + const CMIUtilString strArg = vrTxt.substr(2).c_str(); + return (strArg == GetName()); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the list of CMICmdArgValBase derived option objects found following -// *this long option argument. For example "list-thread-groups [ --recurse 1 ]" -// where 1 is the list of expected option to follow. -// Type: Method. -// Args: None. -// Return: CMICmdArgValListBase::VecArgObjPtr_t & - List of options. -// Throws: None. +// Details: Retrieve the list of CMICmdArgValBase derived option objects found following +// *this long option argument. For example "list-thread-groups [ --recurse 1 ]" +// where 1 is the list of expected option to follow. +// Type: Method. +// Args: None. +// Return: CMICmdArgValListBase::VecArgObjPtr_t & - List of options. +// Throws: None. //-- -const CMICmdArgValListBase::VecArgObjPtr_t & CMICmdArgValOptionLong::GetExpectedOptions( void ) const +const CMICmdArgValListBase::VecArgObjPtr_t & +CMICmdArgValOptionLong::GetExpectedOptions(void) const { - return m_vecArgsExpected; + return m_vecArgsExpected; } - diff --git a/tools/lldb-mi/MICmdArgValOptionLong.h b/tools/lldb-mi/MICmdArgValOptionLong.h index 3baae416c93a..8ff92bf84369 100644 --- a/tools/lldb-mi/MICmdArgValOptionLong.h +++ b/tools/lldb-mi/MICmdArgValOptionLong.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValOptionLong.h +// File: MICmdArgValOptionLong.h // -// Overview: CMICmdArgValOptionLong interface. +// Overview: CMICmdArgValOptionLong interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -29,81 +29,82 @@ class CMICmdArgContext; class CMIUtilString; //++ ============================================================================ -// Details: MI common code class. Command argument class. Arguments object -// needing specialization derived from the CMICmdArgValBase class. -// An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching -// argument and so extract a value from it. -// If *this argument has expected options following it the option objects -// created to hold each of those option's values belong to *this argument -// object and so are deleted when *this object goes out of scope. -// Based on the Interpreter pattern. -// Gotchas: None. -// Authors: Illya Rudkin 16/04/2014. -// Changes: None. +// Details: MI common code class. Command argument class. Arguments object +// needing specialization derived from the CMICmdArgValBase class. +// An argument knows what type of argument it is and how it is to +// interpret the options (context) string to find and validate a matching +// argument and so extract a value from it. +// If *this argument has expected options following it the option objects +// created to hold each of those option's values belong to *this argument +// object and so are deleted when *this object goes out of scope. +// Based on the Interpreter pattern. +// Gotchas: None. +// Authors: Illya Rudkin 16/04/2014. +// Changes: None. //-- class CMICmdArgValOptionLong : public CMICmdArgValListBase { -// Methods: -public: - /* ctor */ CMICmdArgValOptionLong( void ); - /* ctor */ CMICmdArgValOptionLong( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ); - /* ctor */ CMICmdArgValOptionLong( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType, const MIuint vnExpectingNOptions ); - // - bool IsArgLongOption( const CMIUtilString & vrTxt ) const; - const VecArgObjPtr_t & GetExpectedOptions( void ) const; - template< class T1, typename T2 > - bool GetExpectedOption( T2 & vrwValue ) const; - -// Overridden: -public: - // From CMICmdArgValBase - /* dtor */ virtual ~CMICmdArgValOptionLong( void ); - // From CMICmdArgSet::IArg - virtual bool Validate( CMICmdArgContext & vArgContext ); + // Methods: + public: + /* ctor */ CMICmdArgValOptionLong(void); + /* ctor */ CMICmdArgValOptionLong(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); + /* ctor */ CMICmdArgValOptionLong(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, + const ArgValType_e veType, const MIuint vnExpectingNOptions); + // + bool IsArgLongOption(const CMIUtilString &vrTxt) const; + const VecArgObjPtr_t &GetExpectedOptions(void) const; + template bool GetExpectedOption(T2 &vrwValue) const; -// Methods: -protected: - bool ExtractExpectedOptions( CMICmdArgContext & vrwTxt, const MIuint nArgIndex ); + // Overridden: + public: + // From CMICmdArgValBase + /* dtor */ virtual ~CMICmdArgValOptionLong(void); + // From CMICmdArgSet::IArg + virtual bool Validate(CMICmdArgContext &vArgContext); -// Overrideable: -protected: - virtual bool IsArgOptionCorrect( const CMIUtilString & vrTxt ) const; - virtual bool ArgNameMatch( const CMIUtilString & vrTxt ) const; + // Methods: + protected: + bool ExtractExpectedOptions(CMICmdArgContext &vrwTxt, const MIuint nArgIndex); -// Methods: -private: - void Destroy( void ); + // Overrideable: + protected: + virtual bool IsArgOptionCorrect(const CMIUtilString &vrTxt) const; + virtual bool ArgNameMatch(const CMIUtilString &vrTxt) const; -// Attributes: -private: - MIuint m_nExpectingNOptions; // The number of options expected to read following *this argument - VecArgObjPtr_t m_vecArgsExpected; // The option objects holding the value extracted following *this argument - ArgValType_e m_eExpectingOptionType; // The type of options expected to read following *this argument + // Methods: + private: + void Destroy(void); + + // Attributes: + private: + MIuint m_nExpectingNOptions; // The number of options expected to read following *this argument + VecArgObjPtr_t m_vecArgsExpected; // The option objects holding the value extracted following *this argument + ArgValType_e m_eExpectingOptionType; // The type of options expected to read following *this argument }; //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the first argument or option value from the list of 1 or more options -// parsed from the command's options string. -// Type: Template method. -// Args: vrwValue - (W) Templated type return value. -// T1 - The argument value's class type of the data hold in the list of options. -// T2 - The type pf the variable which holds the value wanted. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. List of object was empty. -// Throws: None. +// Details: Retrieve the first argument or option value from the list of 1 or more options +// parsed from the command's options string. +// Type: Template method. +// Args: vrwValue - (W) Templated type return value. +// T1 - The argument value's class type of the data hold in the list of options. +// T2 - The type pf the variable which holds the value wanted. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. List of object was empty. +// Throws: None. //-- -template< class T1, typename T2 > -bool CMICmdArgValOptionLong::GetExpectedOption( T2 & vrwValue ) const +template +bool +CMICmdArgValOptionLong::GetExpectedOption(T2 &vrwValue) const { - const VecArgObjPtr_t & rVecOptions( GetExpectedOptions() ); - VecArgObjPtr_t::const_iterator it2 = rVecOptions.begin(); - if( it2 != rVecOptions.end() ) - { - const T1 * pOption = static_cast< T1 * >( *it2 ); - vrwValue = pOption->GetValue(); - return MIstatus::success; - } + const VecArgObjPtr_t &rVecOptions(GetExpectedOptions()); + VecArgObjPtr_t::const_iterator it2 = rVecOptions.begin(); + if (it2 != rVecOptions.end()) + { + const T1 *pOption = static_cast(*it2); + vrwValue = pOption->GetValue(); + return MIstatus::success; + } - return MIstatus::failure; + return MIstatus::failure; } diff --git a/tools/lldb-mi/MICmdArgValOptionShort.cpp b/tools/lldb-mi/MICmdArgValOptionShort.cpp index 76adb7f11493..5a2b491d3c72 100644 --- a/tools/lldb-mi/MICmdArgValOptionShort.cpp +++ b/tools/lldb-mi/MICmdArgValOptionShort.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValOptionShort.cpp +// File: MICmdArgValOptionShort.cpp // -// Overview: CMICmdArgValOptionShort implementation. +// Overview: CMICmdArgValOptionShort implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -24,105 +24,109 @@ #include "MICmdArgContext.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValOptionShort constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValOptionShort constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValOptionShort::CMICmdArgValOptionShort( void ) +CMICmdArgValOptionShort::CMICmdArgValOptionShort(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValOptionShort constructor. -// Type: Method. -// Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// Return: None. -// Throws: None. +// Details: CMICmdArgValOptionShort constructor. +// Type: Method. +// Args: vrArgName - (R) Argument's name to search by. +// vbMandatory - (R) True = Yes must be present, false = optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// Return: None. +// Throws: None. //-- -CMICmdArgValOptionShort::CMICmdArgValOptionShort( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ) -: CMICmdArgValOptionLong( vrArgName, vbMandatory, vbHandleByCmd ) +CMICmdArgValOptionShort::CMICmdArgValOptionShort(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) + : CMICmdArgValOptionLong(vrArgName, vbMandatory, vbHandleByCmd) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValOptionLong constructor. -// Type: Method. -// Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// veType - (R) The type of argument to look for and create argument object of a certain type. -// vnExpectingNOptions - (R) The number of options expected to read following *this argument. -// Return: None. -// Throws: None. +// Details: CMICmdArgValOptionLong constructor. +// Type: Method. +// Args: vrArgName - (R) Argument's name to search by. +// vbMandatory - (R) True = Yes must be present, false = optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// veType - (R) The type of argument to look for and create argument object of a certain type. +// vnExpectingNOptions - (R) The number of options expected to read following *this argument. +// Return: None. +// Throws: None. //-- -CMICmdArgValOptionShort::CMICmdArgValOptionShort( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType, const MIuint vnExpectingNOptions ) -: CMICmdArgValOptionLong( vrArgName, vbMandatory, vbHandleByCmd, veType, vnExpectingNOptions ) +CMICmdArgValOptionShort::CMICmdArgValOptionShort(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, + const ArgValType_e veType, const MIuint vnExpectingNOptions) + : CMICmdArgValOptionLong(vrArgName, vbMandatory, vbHandleByCmd, veType, vnExpectingNOptions) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValOptionShort destructor. -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValOptionShort destructor. +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValOptionShort::~CMICmdArgValOptionShort( void ) +CMICmdArgValOptionShort::~CMICmdArgValOptionShort(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid short type option argument. -// Type: Method. -// Args: vrTxt - (R) Some text. -// Return: bool - True = yes valid arg, false = no. -// Throws: None. +// Details: Examine the string and determine if it is a valid short type option argument. +// Type: Method. +// Args: vrTxt - (R) Some text. +// Return: bool - True = yes valid arg, false = no. +// Throws: None. //-- -bool CMICmdArgValOptionShort::IsArgShortOption( const CMIUtilString & vrTxt ) const +bool +CMICmdArgValOptionShort::IsArgShortOption(const CMIUtilString &vrTxt) const { - // Look for --someLongOption - MIint nPos = vrTxt.find( "--" ); - if( nPos == 0 ) - return false; - - // Look for -f short option - nPos = vrTxt.find( "-" ); - if( nPos != 0 ) - return false; - - if( vrTxt.length() > 2 ) - return false; + // Look for --someLongOption + MIint nPos = vrTxt.find("--"); + if (nPos == 0) + return false; - return true; + // Look for -f short option + nPos = vrTxt.find("-"); + if (nPos != 0) + return false; + + if (vrTxt.length() > 2) + return false; + + return true; } //++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid short type option argument. -// Long type argument looks like -f some short option. -// Type: Overridden. -// Args: vrTxt - (R) Some text. -// Return: bool - True = yes valid arg, false = no. -// Throws: None. +// Details: Examine the string and determine if it is a valid short type option argument. +// Long type argument looks like -f some short option. +// Type: Overridden. +// Args: vrTxt - (R) Some text. +// Return: bool - True = yes valid arg, false = no. +// Throws: None. //-- -bool CMICmdArgValOptionShort::IsArgOptionCorrect( const CMIUtilString & vrTxt ) const +bool +CMICmdArgValOptionShort::IsArgOptionCorrect(const CMIUtilString &vrTxt) const { - return IsArgShortOption( vrTxt ); + return IsArgShortOption(vrTxt); } //++ ------------------------------------------------------------------------------------ -// Details: Does the argument name of the argument being parsed ATM match the name of -// *this argument object. -// Type: Overridden. -// Args: vrTxt - (R) Some text. -// Return: bool - True = yes arg name matched, false = no. -// Throws: None. +// Details: Does the argument name of the argument being parsed ATM match the name of +// *this argument object. +// Type: Overridden. +// Args: vrTxt - (R) Some text. +// Return: bool - True = yes arg name matched, false = no. +// Throws: None. //-- -bool CMICmdArgValOptionShort::ArgNameMatch( const CMIUtilString & vrTxt ) const +bool +CMICmdArgValOptionShort::ArgNameMatch(const CMIUtilString &vrTxt) const { - const CMIUtilString strArg = vrTxt.substr( 1 ).c_str(); - return (strArg == GetName() ); + const CMIUtilString strArg = vrTxt.substr(1).c_str(); + return (strArg == GetName()); } diff --git a/tools/lldb-mi/MICmdArgValOptionShort.h b/tools/lldb-mi/MICmdArgValOptionShort.h index 7af038377123..3bd38ac72d20 100644 --- a/tools/lldb-mi/MICmdArgValOptionShort.h +++ b/tools/lldb-mi/MICmdArgValOptionShort.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValOptionShort.h +// File: MICmdArgValOptionShort.h // -// Overview: CMICmdArgValOptionShort interface. +// Overview: CMICmdArgValOptionShort interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -29,37 +29,38 @@ class CMICmdArgContext; class CMIUtilString; //++ ============================================================================ -// Details: MI common code class. Command argument class. Arguments object -// needing specialization derived from the CMICmdArgValOptionLong class. -// An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching -// argument and so extract a value from it. -// If *this argument has expected options following it the option objects -// created to hold each of those option's values belong to *this argument -// object and so are deleted when *this object goes out of scope. -// Based on the Interpreter pattern. -// Gotchas: None. -// Authors: Illya Rudkin 16/04/2014. -// Changes: None. +// Details: MI common code class. Command argument class. Arguments object +// needing specialization derived from the CMICmdArgValOptionLong class. +// An argument knows what type of argument it is and how it is to +// interpret the options (context) string to find and validate a matching +// argument and so extract a value from it. +// If *this argument has expected options following it the option objects +// created to hold each of those option's values belong to *this argument +// object and so are deleted when *this object goes out of scope. +// Based on the Interpreter pattern. +// Gotchas: None. +// Authors: Illya Rudkin 16/04/2014. +// Changes: None. //-- class CMICmdArgValOptionShort : public CMICmdArgValOptionLong { -// Methods: -public: - /* ctor */ CMICmdArgValOptionShort( void ); - /* ctor */ CMICmdArgValOptionShort( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ); - /* ctor */ CMICmdArgValOptionShort( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType, const MIuint vnExpectingNOptions ); - // - bool IsArgShortOption( const CMIUtilString & vrTxt ) const; - -// Overridden: -public: - // From CMICmdArgValBase - /* dtor */ virtual ~CMICmdArgValOptionShort( void ); + // Methods: + public: + /* ctor */ CMICmdArgValOptionShort(void); + /* ctor */ CMICmdArgValOptionShort(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); + /* ctor */ CMICmdArgValOptionShort(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, + const ArgValType_e veType, const MIuint vnExpectingNOptions); + // + bool IsArgShortOption(const CMIUtilString &vrTxt) const; -// Overridden: -private: - // From CMICmdArgValOptionLong - virtual bool IsArgOptionCorrect( const CMIUtilString & vrTxt ) const; - virtual bool ArgNameMatch( const CMIUtilString & vrTxt ) const; + // Overridden: + public: + // From CMICmdArgValBase + /* dtor */ virtual ~CMICmdArgValOptionShort(void); + + // Overridden: + private: + // From CMICmdArgValOptionLong + virtual bool IsArgOptionCorrect(const CMIUtilString &vrTxt) const; + virtual bool ArgNameMatch(const CMIUtilString &vrTxt) const; }; diff --git a/tools/lldb-mi/MICmdArgValString.cpp b/tools/lldb-mi/MICmdArgValString.cpp index 06818b1dc571..c09eead072d1 100644 --- a/tools/lldb-mi/MICmdArgValString.cpp +++ b/tools/lldb-mi/MICmdArgValString.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValString.cpp +// File: MICmdArgValString.cpp // -// Overview: CMICmdArgValString implementation. +// Overview: CMICmdArgValString implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -24,479 +24,492 @@ #include "MICmdArgContext.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValString constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValString constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValString::CMICmdArgValString( void ) -: m_bHandleQuotedString( false ) -, m_bAcceptNumbers( false ) -, m_bHandleDirPaths( false ) -, m_bHandleAnything( false ) +CMICmdArgValString::CMICmdArgValString(void) + : m_bHandleQuotedString(false) + , m_bAcceptNumbers(false) + , m_bHandleDirPaths(false) + , m_bHandleAnything(false) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValString constructor. -// Type: Method. -// Args: vbAnything - (R) True = Parse a string and accept anything, false = do not accept anything. -// Return: None. -// Throws: None. +// Details: CMICmdArgValString constructor. +// Type: Method. +// Args: vbAnything - (R) True = Parse a string and accept anything, false = do not accept anything. +// Return: None. +// Throws: None. //-- -CMICmdArgValString::CMICmdArgValString( const bool vbAnything ) -: m_bHandleQuotedString( false ) -, m_bAcceptNumbers( false ) -, m_bHandleDirPaths( false ) -, m_bHandleAnything( vbAnything ) +CMICmdArgValString::CMICmdArgValString(const bool vbAnything) + : m_bHandleQuotedString(false) + , m_bAcceptNumbers(false) + , m_bHandleDirPaths(false) + , m_bHandleAnything(vbAnything) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValString constructor. -// Type: Method. -// Args: vbHandleQuotes - (R) True = Parse a string surrounded by quotes spaces are not delimitors, false = only text up to next delimiting space character. -// vbAcceptNumbers - (R) True = Parse a string and accept as a number if number, false = numbers not recognised as string types. -// vbHandleDirPaths - (R) True = Parse a string and accept as a file path if a path, false = file paths are not recognised as string types. -// Return: None. -// Throws: None. +// Details: CMICmdArgValString constructor. +// Type: Method. +// Args: vbHandleQuotes - (R) True = Parse a string surrounded by quotes spaces are not delimitors, false = only text up to +// next delimiting space character. +// vbAcceptNumbers - (R) True = Parse a string and accept as a number if number, false = numbers not recognised +// as string types. +// vbHandleDirPaths - (R) True = Parse a string and accept as a file path if a path, false = file paths are not +// recognised as string types. +// Return: None. +// Throws: None. //-- -CMICmdArgValString::CMICmdArgValString( const bool vbHandleQuotes, const bool vbAcceptNumbers, const bool vbHandleDirPaths ) -: m_bHandleQuotedString( vbHandleQuotes ) -, m_bAcceptNumbers( vbAcceptNumbers ) -, m_bHandleDirPaths( vbHandleDirPaths ) -, m_bHandleAnything( false ) +CMICmdArgValString::CMICmdArgValString(const bool vbHandleQuotes, const bool vbAcceptNumbers, const bool vbHandleDirPaths) + : m_bHandleQuotedString(vbHandleQuotes) + , m_bAcceptNumbers(vbAcceptNumbers) + , m_bHandleDirPaths(vbHandleDirPaths) + , m_bHandleAnything(false) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValString constructor. -// Type: Method. -// Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// vbHandleQuotes - (R) True = Parse a string surrounded by quotes spaces are not delimitors, false = only text up to next delimiting space character. (Dflt = false) -// vbAcceptNumbers - (R) True = Parse a string and accept as a number if number, false = numbers not recognised as string types. (Dflt = false) -// Return: None. -// Throws: None. +// Details: CMICmdArgValString constructor. +// Type: Method. +// Args: vrArgName - (R) Argument's name to search by. +// vbMandatory - (R) True = Yes must be present, false = optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// vbHandleQuotes - (R) True = Parse a string surrounded by quotes spaces are not delimitors, false = only text up to +// next delimiting space character. (Dflt = false) +// vbAcceptNumbers - (R) True = Parse a string and accept as a number if number, false = numbers not recognised as +// string types. (Dflt = false) +// Return: None. +// Throws: None. //-- -CMICmdArgValString::CMICmdArgValString( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const bool vbHandleQuotes /* = false */, const bool vbAcceptNumbers /* = false */ ) -: CMICmdArgValBaseTemplate( vrArgName, vbMandatory, vbHandleByCmd ) -, m_bHandleQuotedString( vbHandleQuotes ) -, m_bAcceptNumbers( vbAcceptNumbers ) -, m_bHandleDirPaths( false ) -, m_bHandleAnything( false ) +CMICmdArgValString::CMICmdArgValString(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, + const bool vbHandleQuotes /* = false */, const bool vbAcceptNumbers /* = false */) + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) + , m_bHandleQuotedString(vbHandleQuotes) + , m_bAcceptNumbers(vbAcceptNumbers) + , m_bHandleDirPaths(false) + , m_bHandleAnything(false) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValString destructor. -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValString destructor. +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValString::~CMICmdArgValString( void ) +CMICmdArgValString::~CMICmdArgValString(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the value *this -// argument is looking for. -// Type: Overridden. -// Args: vrwArgContext - (RW) The command's argument options string. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Parse the command's argument options string and try to extract the value *this +// argument is looking for. +// Type: Overridden. +// Args: vrwArgContext - (RW) The command's argument options string. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgValString::Validate( CMICmdArgContext & vrwArgContext ) +bool +CMICmdArgValString::Validate(CMICmdArgContext &vrwArgContext) { - if( vrwArgContext.IsEmpty() ) - return MIstatus::success; + if (vrwArgContext.IsEmpty()) + return MIstatus::success; - if( m_bHandleQuotedString ) - return (ValidateQuotedText( vrwArgContext ) || ValidateQuotedTextEmbedded( vrwArgContext ) ); + if (m_bHandleQuotedString) + return (ValidateQuotedText(vrwArgContext) || ValidateQuotedTextEmbedded(vrwArgContext)); - return ValidateSingleText( vrwArgContext ); + return ValidateSingleText(vrwArgContext); } //++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract only the next -// word delimited by the next space. -// Type: Method. -// Args: vrwArgContext - (RW) The command's argument options string. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Parse the command's argument options string and try to extract only the next +// word delimited by the next space. +// Type: Method. +// Args: vrwArgContext - (RW) The command's argument options string. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgValString::ValidateSingleText( CMICmdArgContext & vrwArgContext ) +bool +CMICmdArgValString::ValidateSingleText(CMICmdArgContext &vrwArgContext) { - if( vrwArgContext.GetNumberArgsPresent() == 1 ) - { - const CMIUtilString & rArg( vrwArgContext.GetArgsLeftToParse() ); - if( IsStringArg( rArg ) ) - { - m_bFound = true; - m_bValid = true; - m_argValue = rArg; - vrwArgContext.RemoveArg( rArg ); - return MIstatus::success; - } - else - return MIstatus::failure; - } - - // More than one option... - const CMIUtilString::VecString_t vecOptions( vrwArgContext.GetArgs() ); - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while( it != vecOptions.end() ) - { - const CMIUtilString & rArg( *it ); - if( IsStringArg( rArg ) ) - { - m_bFound = true; - - if( vrwArgContext.RemoveArg( rArg ) ) - { - m_bValid = true; - m_argValue = rArg; - return MIstatus::success; - } - else - return MIstatus::failure; - } - - // Next - ++it; - } - - return MIstatus::failure; + if (vrwArgContext.GetNumberArgsPresent() == 1) + { + const CMIUtilString &rArg(vrwArgContext.GetArgsLeftToParse()); + if (IsStringArg(rArg)) + { + m_bFound = true; + m_bValid = true; + m_argValue = rArg; + vrwArgContext.RemoveArg(rArg); + return MIstatus::success; + } + else + return MIstatus::failure; + } + + // More than one option... + const CMIUtilString::VecString_t vecOptions(vrwArgContext.GetArgs()); + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) + { + const CMIUtilString &rArg(*it); + if (IsStringArg(rArg)) + { + m_bFound = true; + + if (vrwArgContext.RemoveArg(rArg)) + { + m_bValid = true; + m_argValue = rArg; + return MIstatus::success; + } + else + return MIstatus::failure; + } + + // Next + ++it; + } + + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract all the words -// between quotes then delimited by the next space. Can fall through to -// ValidateSingleText() or ValidateQuotedQuotedTextEmbedded(). -// Type: Method. -// Args: vrwArgContext - (RW) The command's argument options string. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Parse the command's argument options string and try to extract all the words +// between quotes then delimited by the next space. Can fall through to +// ValidateSingleText() or ValidateQuotedQuotedTextEmbedded(). +// Type: Method. +// Args: vrwArgContext - (RW) The command's argument options string. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgValString::ValidateQuotedText( CMICmdArgContext & vrwArgContext ) +bool +CMICmdArgValString::ValidateQuotedText(CMICmdArgContext &vrwArgContext) { - // CODETAG_QUOTEDTEXT_SIMILAR_CODE - CMIUtilString strOptions = vrwArgContext.GetArgsLeftToParse(); - const MIchar cQuote = '"'; - - // Look for first quote of two - MIint nPos = strOptions.find( cQuote ); - if( nPos == (MIint) std::string::npos ) - return ValidateSingleText( vrwArgContext ); - - // Is one and only quote at end of the string - const MIint nLen = strOptions.length(); - if( nPos == (MIint)(nLen - 1) ) - return MIstatus::failure; - - // Quote must be the first character in the string or be preceeded by a space - if( (nPos > 0) && (strOptions[ nPos - 1 ] != ' ') ) - return MIstatus::failure; - - // Need to find the other quote - const MIint nPos2 = strOptions.rfind( cQuote ); - if( nPos2 == (MIint) std::string::npos ) - return MIstatus::failure; - - // Is there quotes surrounding string formatting embedded quotes - if( IsStringArgQuotedQuotedTextEmbedded( strOptions ) ) - return ValidateQuotedQuotedTextEmbedded( vrwArgContext ); - - // Make sure not same back quote, need two quotes - if( nPos == nPos2 ) - return MIstatus::failure; - - // Extract quoted text - const CMIUtilString strQuotedTxt = strOptions.substr( nPos, nPos2 - nPos + 1 ).c_str(); - if( vrwArgContext.RemoveArg( strQuotedTxt ) ) - { - m_bFound = true; - m_bValid = true; - m_argValue = strOptions.substr( nPos + 1, nPos2 - nPos - 1 ).c_str(); - return MIstatus::success; - } - - return MIstatus::failure; + // CODETAG_QUOTEDTEXT_SIMILAR_CODE + CMIUtilString strOptions = vrwArgContext.GetArgsLeftToParse(); + const MIchar cQuote = '"'; + + // Look for first quote of two + MIint nPos = strOptions.find(cQuote); + if (nPos == (MIint)std::string::npos) + return ValidateSingleText(vrwArgContext); + + // Is one and only quote at end of the string + const MIint nLen = strOptions.length(); + if (nPos == (MIint)(nLen - 1)) + return MIstatus::failure; + + // Quote must be the first character in the string or be preceeded by a space + if ((nPos > 0) && (strOptions[nPos - 1] != ' ')) + return MIstatus::failure; + + // Need to find the other quote + const MIint nPos2 = strOptions.rfind(cQuote); + if (nPos2 == (MIint)std::string::npos) + return MIstatus::failure; + + // Is there quotes surrounding string formatting embedded quotes + if (IsStringArgQuotedQuotedTextEmbedded(strOptions)) + return ValidateQuotedQuotedTextEmbedded(vrwArgContext); + + // Make sure not same back quote, need two quotes + if (nPos == nPos2) + return MIstatus::failure; + + // Extract quoted text + const CMIUtilString strQuotedTxt = strOptions.substr(nPos, nPos2 - nPos + 1).c_str(); + if (vrwArgContext.RemoveArg(strQuotedTxt)) + { + m_bFound = true; + m_bValid = true; + m_argValue = strOptions.substr(nPos + 1, nPos2 - nPos - 1).c_str(); + return MIstatus::success; + } + + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract all the words -// between quotes then delimited by the next space. If there any string format -// characters '\\' used to embed quotes these are ignored i.e. "\\\"%5d\\\"" -// becomes "%5d". Can fall through to ValidateQuotedText(). -// Type: Method. -// Args: vrwArgContext - (RW) The command's argument options string. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Parse the command's argument options string and try to extract all the words +// between quotes then delimited by the next space. If there any string format +// characters '\\' used to embed quotes these are ignored i.e. "\\\"%5d\\\"" +// becomes "%5d". Can fall through to ValidateQuotedText(). +// Type: Method. +// Args: vrwArgContext - (RW) The command's argument options string. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgValString::ValidateQuotedTextEmbedded( CMICmdArgContext & vrwArgContext ) +bool +CMICmdArgValString::ValidateQuotedTextEmbedded(CMICmdArgContext &vrwArgContext) { - // CODETAG_QUOTEDTEXT_SIMILAR_CODE - CMIUtilString strOptions = vrwArgContext.GetArgsLeftToParse(); - const MIchar cBckSlash = '\\'; - const MIint nPos = strOptions.find( cBckSlash ); - if( nPos == (MIint) std::string::npos ) - return ValidateQuotedText( vrwArgContext ); - - // Back slash must be the first character in the string or be preceeded by a space - // or '\\' - const MIchar cSpace = ' '; - if( (nPos > 0) && (strOptions[ nPos - 1 ] != cSpace) ) - return MIstatus::failure; - - // Need to find the other back slash - const MIint nPos2 = strOptions.rfind( cBckSlash ); - if( nPos2 == (MIint) std::string::npos ) - return MIstatus::failure; - - // Make sure not same back slash, need two slashs - if( nPos == nPos2 ) - return MIstatus::failure; - - // Look for the two quotes - const MIint nLen = strOptions.length(); - const MIchar cQuote = '"'; - const MIint nPosQuote1 = nPos + 1; - const MIint nPosQuote2 = (nPos2 < nLen) ? nPos2 + 1 : nPos2; - if( (nPosQuote1 != nPosQuote2) && - (strOptions[ nPosQuote1 ] != cQuote) && (strOptions[ nPosQuote2 ] != cQuote) ) - return MIstatus::failure; - - // Extract quoted text - const CMIUtilString strQuotedTxt = strOptions.substr( nPos, nPosQuote2 - nPos + 1 ).c_str(); - if( vrwArgContext.RemoveArg( strQuotedTxt ) ) - { - m_bFound = true; - m_bValid = true; - m_argValue = strQuotedTxt; - return MIstatus::success; - } - - return MIstatus::failure; + // CODETAG_QUOTEDTEXT_SIMILAR_CODE + CMIUtilString strOptions = vrwArgContext.GetArgsLeftToParse(); + const MIchar cBckSlash = '\\'; + const MIint nPos = strOptions.find(cBckSlash); + if (nPos == (MIint)std::string::npos) + return ValidateQuotedText(vrwArgContext); + + // Back slash must be the first character in the string or be preceeded by a space + // or '\\' + const MIchar cSpace = ' '; + if ((nPos > 0) && (strOptions[nPos - 1] != cSpace)) + return MIstatus::failure; + + // Need to find the other back slash + const MIint nPos2 = strOptions.rfind(cBckSlash); + if (nPos2 == (MIint)std::string::npos) + return MIstatus::failure; + + // Make sure not same back slash, need two slashs + if (nPos == nPos2) + return MIstatus::failure; + + // Look for the two quotes + const MIint nLen = strOptions.length(); + const MIchar cQuote = '"'; + const MIint nPosQuote1 = nPos + 1; + const MIint nPosQuote2 = (nPos2 < nLen) ? nPos2 + 1 : nPos2; + if ((nPosQuote1 != nPosQuote2) && (strOptions[nPosQuote1] != cQuote) && (strOptions[nPosQuote2] != cQuote)) + return MIstatus::failure; + + // Extract quoted text + const CMIUtilString strQuotedTxt = strOptions.substr(nPos, nPosQuote2 - nPos + 1).c_str(); + if (vrwArgContext.RemoveArg(strQuotedTxt)) + { + m_bFound = true; + m_bValid = true; + m_argValue = strQuotedTxt; + return MIstatus::success; + } + + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract all the words -// between quotes then delimited by the next space. If there any string format -// characters '\\' used to embed quotes these are ignored i.e. "\\\"%5d\\\"" -// becomes "%5d". -// Type: Method. -// Args: vrwArgContext - (RW) The command's argument options string. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Parse the command's argument options string and try to extract all the words +// between quotes then delimited by the next space. If there any string format +// characters '\\' used to embed quotes these are ignored i.e. "\\\"%5d\\\"" +// becomes "%5d". +// Type: Method. +// Args: vrwArgContext - (RW) The command's argument options string. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgValString::ValidateQuotedQuotedTextEmbedded( CMICmdArgContext & vrwArgContext ) +bool +CMICmdArgValString::ValidateQuotedQuotedTextEmbedded(CMICmdArgContext &vrwArgContext) { - // CODETAG_QUOTEDTEXT_SIMILAR_CODE - CMIUtilString strOptions = vrwArgContext.GetArgsLeftToParse(); - const MIint nPos = strOptions.find( "\"\\\"" ); - if( nPos == (MIint) std::string::npos ) - return MIstatus::failure; - - const MIint nPos2 = strOptions.rfind( "\\\"\"" ); - if( nPos2 == (MIint) std::string::npos ) - return MIstatus::failure; - - const MIint nLen = strOptions.length(); - if( (nLen > 5) && ((nPos + 2) == (nPos2 - 2)) ) - return MIstatus::failure; - - // Quote must be the first character in the string or be preceeded by a space - // or '\\' - const MIchar cSpace = ' '; - if( (nPos > 0) && (strOptions[ nPos - 1 ] != cSpace) ) - return MIstatus::failure; - - // Extract quoted text - const CMIUtilString strQuotedTxt = strOptions.substr( nPos, nPos2 - nPos + 3 ).c_str(); - if( vrwArgContext.RemoveArg( strQuotedTxt ) ) - { - m_bFound = true; - m_bValid = true; - m_argValue = strQuotedTxt; - return MIstatus::success; - } - - return MIstatus::failure; + // CODETAG_QUOTEDTEXT_SIMILAR_CODE + CMIUtilString strOptions = vrwArgContext.GetArgsLeftToParse(); + const MIint nPos = strOptions.find("\"\\\""); + if (nPos == (MIint)std::string::npos) + return MIstatus::failure; + + const MIint nPos2 = strOptions.rfind("\\\"\""); + if (nPos2 == (MIint)std::string::npos) + return MIstatus::failure; + + const MIint nLen = strOptions.length(); + if ((nLen > 5) && ((nPos + 2) == (nPos2 - 2))) + return MIstatus::failure; + + // Quote must be the first character in the string or be preceeded by a space + // or '\\' + const MIchar cSpace = ' '; + if ((nPos > 0) && (strOptions[nPos - 1] != cSpace)) + return MIstatus::failure; + + // Extract quoted text + const CMIUtilString strQuotedTxt = strOptions.substr(nPos, nPos2 - nPos + 3).c_str(); + if (vrwArgContext.RemoveArg(strQuotedTxt)) + { + m_bFound = true; + m_bValid = true; + m_argValue = strQuotedTxt; + return MIstatus::success; + } + + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument. -// Type: Method. -// Args: vrTxt - (R) Some text. -// Return: bool - True = yes valid arg, false = no. -// Throws: None. +// Details: Examine the string and determine if it is a valid string type argument. +// Type: Method. +// Args: vrTxt - (R) Some text. +// Return: bool - True = yes valid arg, false = no. +// Throws: None. //-- -bool CMICmdArgValString::IsStringArg( const CMIUtilString & vrTxt ) const +bool +CMICmdArgValString::IsStringArg(const CMIUtilString &vrTxt) const { - if( m_bHandleQuotedString ) - return (IsStringArgQuotedText( vrTxt ) || - IsStringArgQuotedTextEmbedded( vrTxt ) || - IsStringArgQuotedQuotedTextEmbedded( vrTxt ) || - IsStringArgSingleText( vrTxt ) ); // Still test for this as could just be one word still - - return IsStringArgSingleText( vrTxt ); + if (m_bHandleQuotedString) + return (IsStringArgQuotedText(vrTxt) || IsStringArgQuotedTextEmbedded(vrTxt) || IsStringArgQuotedQuotedTextEmbedded(vrTxt) || + IsStringArgSingleText(vrTxt)); // Still test for this as could just be one word still + + return IsStringArgSingleText(vrTxt); } //++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument or -// option value. If the string looks like a long option, short option, a thread -// group ID or just a number it is rejected as a string type value. There is an -// option to allow the string to accept a number as a string type. -// Type: Method. -// Args: vrTxt - (R) Some text. -// Return: bool - True = yes valid argument value, false = something else. -// Throws: None. +// Details: Examine the string and determine if it is a valid string type argument or +// option value. If the string looks like a long option, short option, a thread +// group ID or just a number it is rejected as a string type value. There is an +// option to allow the string to accept a number as a string type. +// Type: Method. +// Args: vrTxt - (R) Some text. +// Return: bool - True = yes valid argument value, false = something else. +// Throws: None. //-- -bool CMICmdArgValString::IsStringArgSingleText( const CMIUtilString & vrTxt ) const +bool +CMICmdArgValString::IsStringArgSingleText(const CMIUtilString &vrTxt) const { - // Accept anything as string word - if( m_bHandleAnything ) - return true; - - if( !m_bHandleDirPaths ) - { - // Look for directory file paths, if found reject - const bool bHavePosSlash = (vrTxt.find_first_of( "/" ) != std::string::npos); - const bool bHaveBckSlash = (vrTxt.find_first_of( "\\" ) != std::string::npos); - if( bHavePosSlash || bHaveBckSlash ) - return false; - } - - // Look for --someLongOption, if found reject - if( 0 == vrTxt.find( "--" ) ) - return false; - - // Look for -f type short options, if found reject - if( (0 == vrTxt.find( "-" )) && (vrTxt.length() == 2) ) - return false; - - // Look for thread group i1 i2 i3...., if found reject - if( (vrTxt.find( "i" ) == 0) && ::isdigit( vrTxt[ 1 ]) ) - return false; - - // Look for numbers, if found reject - if( !m_bAcceptNumbers && vrTxt.IsNumber() ) - return false; - - return true; + // Accept anything as string word + if (m_bHandleAnything) + return true; + + if (!m_bHandleDirPaths) + { + // Look for directory file paths, if found reject + const bool bHavePosSlash = (vrTxt.find_first_of("/") != std::string::npos); + const bool bHaveBckSlash = (vrTxt.find_first_of("\\") != std::string::npos); + if (bHavePosSlash || bHaveBckSlash) + return false; + } + + // Look for --someLongOption, if found reject + if (0 == vrTxt.find("--")) + return false; + + // Look for -f type short options, if found reject + if ((0 == vrTxt.find("-")) && (vrTxt.length() == 2)) + return false; + + // Look for thread group i1 i2 i3...., if found reject + if ((vrTxt.find("i") == 0) && ::isdigit(vrTxt[1])) + return false; + + // Look for numbers, if found reject + if (!m_bAcceptNumbers && vrTxt.IsNumber()) + return false; + + return true; } //++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument. -// Take into account quotes surrounding the text. Note this function falls -// through to IsStringArgSingleText() should the criteria match fail. -// Type: Method. -// Args: vrTxt - (R) Some text. -// Return: bool - True = yes valid arg, false = no. -// Throws: None. +// Details: Examine the string and determine if it is a valid string type argument. +// Take into account quotes surrounding the text. Note this function falls +// through to IsStringArgSingleText() should the criteria match fail. +// Type: Method. +// Args: vrTxt - (R) Some text. +// Return: bool - True = yes valid arg, false = no. +// Throws: None. //-- -bool CMICmdArgValString::IsStringArgQuotedText( const CMIUtilString & vrTxt ) const +bool +CMICmdArgValString::IsStringArgQuotedText(const CMIUtilString &vrTxt) const { - // CODETAG_QUOTEDTEXT_SIMILAR_CODE - const MIchar cQuote = '"'; - const MIint nPos = vrTxt.find( cQuote ); - if( nPos == (MIint) std::string::npos ) - return false; - - // Is one and only quote at end of the string - if( nPos == (MIint)(vrTxt.length() - 1) ) - return false; - - // Quote must be the first character in the string or be preceeded by a space - // Also check for embedded string formating quote - const MIchar cBckSlash = '\\'; - const MIchar cSpace = ' '; - if( (nPos > 1) && (vrTxt[ nPos - 1 ] == cBckSlash) && (vrTxt[ nPos - 2 ] != cSpace) ) - { - return false; - } - if( (nPos > 0) && (vrTxt[ nPos - 1 ] != cSpace) ) - return false; - - // Need to find the other quote - const MIint nPos2 = vrTxt.rfind( cQuote ); - if( nPos2 == (MIint) std::string::npos ) - return false; - - // Make sure not same quote, need two quotes - if( nPos == nPos2 ) - return MIstatus::failure; - - return true; + // CODETAG_QUOTEDTEXT_SIMILAR_CODE + const MIchar cQuote = '"'; + const MIint nPos = vrTxt.find(cQuote); + if (nPos == (MIint)std::string::npos) + return false; + + // Is one and only quote at end of the string + if (nPos == (MIint)(vrTxt.length() - 1)) + return false; + + // Quote must be the first character in the string or be preceeded by a space + // Also check for embedded string formating quote + const MIchar cBckSlash = '\\'; + const MIchar cSpace = ' '; + if ((nPos > 1) && (vrTxt[nPos - 1] == cBckSlash) && (vrTxt[nPos - 2] != cSpace)) + { + return false; + } + if ((nPos > 0) && (vrTxt[nPos - 1] != cSpace)) + return false; + + // Need to find the other quote + const MIint nPos2 = vrTxt.rfind(cQuote); + if (nPos2 == (MIint)std::string::npos) + return false; + + // Make sure not same quote, need two quotes + if (nPos == nPos2) + return MIstatus::failure; + + return true; } //++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument. -// Take into account quotes surrounding the text. Take into account string format -// embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this function falls -// through to IsStringArgQuotedText() should the criteria match fail. -// Type: Method. -// Args: vrTxt - (R) Some text. -// Return: bool - True = yes valid arg, false = no. -// Throws: None. +// Details: Examine the string and determine if it is a valid string type argument. +// Take into account quotes surrounding the text. Take into account string format +// embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this function falls +// through to IsStringArgQuotedText() should the criteria match fail. +// Type: Method. +// Args: vrTxt - (R) Some text. +// Return: bool - True = yes valid arg, false = no. +// Throws: None. //-- -bool CMICmdArgValString::IsStringArgQuotedTextEmbedded( const CMIUtilString & vrTxt ) const +bool +CMICmdArgValString::IsStringArgQuotedTextEmbedded(const CMIUtilString &vrTxt) const { - // CODETAG_QUOTEDTEXT_SIMILAR_CODE - const MIchar cBckSlash = '\\'; - const MIint nPos = vrTxt.find( cBckSlash ); - if( nPos == (MIint) std::string::npos ) - return false; - - // Slash must be the first character in the string or be preceeded by a space - const MIchar cSpace = ' '; - if( (nPos > 0) && (vrTxt[ nPos - 1 ] != cSpace) ) - return false; - - // Need to find the other matching slash - const MIint nPos2 = vrTxt.rfind( cBckSlash ); - if( nPos2 == (MIint) std::string::npos ) - return false; - - // Make sure not same back slash, need two slashs - if( nPos == nPos2 ) - return MIstatus::failure; - - return false; + // CODETAG_QUOTEDTEXT_SIMILAR_CODE + const MIchar cBckSlash = '\\'; + const MIint nPos = vrTxt.find(cBckSlash); + if (nPos == (MIint)std::string::npos) + return false; + + // Slash must be the first character in the string or be preceeded by a space + const MIchar cSpace = ' '; + if ((nPos > 0) && (vrTxt[nPos - 1] != cSpace)) + return false; + + // Need to find the other matching slash + const MIint nPos2 = vrTxt.rfind(cBckSlash); + if (nPos2 == (MIint)std::string::npos) + return false; + + // Make sure not same back slash, need two slashs + if (nPos == nPos2) + return MIstatus::failure; + + return false; } //++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument. -// Take into account quotes surrounding the text. Take into account string format -// embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this function falls -// through to IsStringArgQuotedTextEmbedded() should the criteria match fail. -// Type: Method. -// Args: vrTxt - (R) Some text. -// Return: bool - True = yes valid arg, false = no. -// Throws: None. +// Details: Examine the string and determine if it is a valid string type argument. +// Take into account quotes surrounding the text. Take into account string format +// embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this function falls +// through to IsStringArgQuotedTextEmbedded() should the criteria match fail. +// Type: Method. +// Args: vrTxt - (R) Some text. +// Return: bool - True = yes valid arg, false = no. +// Throws: None. //-- -bool CMICmdArgValString::IsStringArgQuotedQuotedTextEmbedded( const CMIUtilString & vrTxt ) const +bool +CMICmdArgValString::IsStringArgQuotedQuotedTextEmbedded(const CMIUtilString &vrTxt) const { - const MIint nPos = vrTxt.find( "\"\\\"" ); - if( nPos == (MIint) std::string::npos ) - return false; - - const MIint nPos2 = vrTxt.rfind( "\\\"\"" ); - if( nPos2 == (MIint) std::string::npos ) - return false; - - const MIint nLen = vrTxt.length(); - if( (nLen > 5) && ((nPos + 2) == (nPos2 - 2)) ) - return false; - - return true; + const MIint nPos = vrTxt.find("\"\\\""); + if (nPos == (MIint)std::string::npos) + return false; + + const MIint nPos2 = vrTxt.rfind("\\\"\""); + if (nPos2 == (MIint)std::string::npos) + return false; + + const MIint nLen = vrTxt.length(); + if ((nLen > 5) && ((nPos + 2) == (nPos2 - 2))) + return false; + + return true; } diff --git a/tools/lldb-mi/MICmdArgValString.h b/tools/lldb-mi/MICmdArgValString.h index ab411a02dc88..58f9ee4f32c3 100644 --- a/tools/lldb-mi/MICmdArgValString.h +++ b/tools/lldb-mi/MICmdArgValString.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValString.h +// File: MICmdArgValString.h // -// Overview: CMICmdArgValString interface. +// Overview: CMICmdArgValString interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -28,49 +28,52 @@ class CMICmdArgContext; //++ ============================================================================ -// Details: MI common code class. Command argument class. Arguments object -// needing specialization derived from the CMICmdArgValBase class. -// An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching -// argument and so extract a value from it . -// Based on the Interpreter pattern. -// Gotchas: None. -// Authors: Illya Rudkin 15/04/2014. -// Changes: None. +// Details: MI common code class. Command argument class. Arguments object +// needing specialization derived from the CMICmdArgValBase class. +// An argument knows what type of argument it is and how it is to +// interpret the options (context) string to find and validate a matching +// argument and so extract a value from it . +// Based on the Interpreter pattern. +// Gotchas: None. +// Authors: Illya Rudkin 15/04/2014. +// Changes: None. //-- -class CMICmdArgValString : public CMICmdArgValBaseTemplate< CMIUtilString > +class CMICmdArgValString : public CMICmdArgValBaseTemplate { -// Methods: -public: - /* ctor */ CMICmdArgValString( void ); - /* ctor */ CMICmdArgValString( const bool vbAnything ); - /* ctor */ CMICmdArgValString( const bool vbHandleQuotes, const bool vbAcceptNumbers, const bool vbHandleDirPaths ); - /* ctor */ CMICmdArgValString( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const bool vbHandleQuotes = false, const bool vbAcceptNumbers = false ); - // - bool IsStringArg( const CMIUtilString & vrTxt ) const; + // Methods: + public: + /* ctor */ CMICmdArgValString(void); + /* ctor */ CMICmdArgValString(const bool vbAnything); + /* ctor */ CMICmdArgValString(const bool vbHandleQuotes, const bool vbAcceptNumbers, const bool vbHandleDirPaths); + /* ctor */ CMICmdArgValString(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, + const bool vbHandleQuotes = false, const bool vbAcceptNumbers = false); + // + bool IsStringArg(const CMIUtilString &vrTxt) const; -// Overridden: -public: - // From CMICmdArgValBase - /* dtor */ virtual ~CMICmdArgValString( void ); - // From CMICmdArgSet::IArg - virtual bool Validate( CMICmdArgContext & vrwArgContext ); + // Overridden: + public: + // From CMICmdArgValBase + /* dtor */ virtual ~CMICmdArgValString(void); + // From CMICmdArgSet::IArg + virtual bool Validate(CMICmdArgContext &vrwArgContext); -// Methods: -private: - bool ValidateSingleText( CMICmdArgContext & vrwArgContext ); - bool ValidateQuotedText( CMICmdArgContext & vrwArgContext ); - bool ValidateQuotedTextEmbedded( CMICmdArgContext & vrwArgContext ); - bool ValidateQuotedQuotedTextEmbedded( CMICmdArgContext & vrwArgContext ); - bool IsStringArgSingleText( const CMIUtilString & vrTxt ) const; - bool IsStringArgQuotedText( const CMIUtilString & vrTxt ) const; - bool IsStringArgQuotedTextEmbedded( const CMIUtilString & vrTxt ) const; - bool IsStringArgQuotedQuotedTextEmbedded( const CMIUtilString & vrTxt ) const; + // Methods: + private: + bool ValidateSingleText(CMICmdArgContext &vrwArgContext); + bool ValidateQuotedText(CMICmdArgContext &vrwArgContext); + bool ValidateQuotedTextEmbedded(CMICmdArgContext &vrwArgContext); + bool ValidateQuotedQuotedTextEmbedded(CMICmdArgContext &vrwArgContext); + bool IsStringArgSingleText(const CMIUtilString &vrTxt) const; + bool IsStringArgQuotedText(const CMIUtilString &vrTxt) const; + bool IsStringArgQuotedTextEmbedded(const CMIUtilString &vrTxt) const; + bool IsStringArgQuotedQuotedTextEmbedded(const CMIUtilString &vrTxt) const; -// Attribute: -private: - bool m_bHandleQuotedString; // True = Parse a string surrounded by quotes spaces are not delimitors, false = only text up to next delimiting space character - bool m_bAcceptNumbers; // True = Parse a string and accept as a number if number, false = numbers not recognised as string types - bool m_bHandleDirPaths; // True = Parse a string and accept directory file style string if present, false = directory file path not accepted - bool m_bHandleAnything; // True = Parse a string and accept anything if present, false = validate for criteria matches + // Attribute: + private: + bool m_bHandleQuotedString; // True = Parse a string surrounded by quotes spaces are not delimitors, false = only text up to next + // delimiting space character + bool m_bAcceptNumbers; // True = Parse a string and accept as a number if number, false = numbers not recognised as string types + bool m_bHandleDirPaths; // True = Parse a string and accept directory file style string if present, false = directory file path not + // accepted + bool m_bHandleAnything; // True = Parse a string and accept anything if present, false = validate for criteria matches }; diff --git a/tools/lldb-mi/MICmdArgValThreadGrp.cpp b/tools/lldb-mi/MICmdArgValThreadGrp.cpp index 7d3290482119..606c615dfca2 100644 --- a/tools/lldb-mi/MICmdArgValThreadGrp.cpp +++ b/tools/lldb-mi/MICmdArgValThreadGrp.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValThreadGrp.cpp +// File: MICmdArgValThreadGrp.cpp // -// Overview: CMICmdArgValThreadGrp implementation. +// Overview: CMICmdArgValThreadGrp implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -24,150 +24,153 @@ #include "MICmdArgContext.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValThreadGrp constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValThreadGrp constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValThreadGrp::CMICmdArgValThreadGrp( void ) -: m_nThreadGrp( 0 ) +CMICmdArgValThreadGrp::CMICmdArgValThreadGrp(void) + : m_nThreadGrp(0) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValThreadGrp constructor. -// Type: Method. -// Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// Return: None. -// Throws: None. +// Details: CMICmdArgValThreadGrp constructor. +// Type: Method. +// Args: vrArgName - (R) Argument's name to search by. +// vbMandatory - (R) True = Yes must be present, false = optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// Return: None. +// Throws: None. //-- -CMICmdArgValThreadGrp::CMICmdArgValThreadGrp( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ) -: CMICmdArgValBaseTemplate( vrArgName, vbMandatory, vbHandleByCmd ) -, m_nThreadGrp( 0 ) +CMICmdArgValThreadGrp::CMICmdArgValThreadGrp(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) + , m_nThreadGrp(0) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdArgValThreadGrp destructor. -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdArgValThreadGrp destructor. +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdArgValThreadGrp::~CMICmdArgValThreadGrp( void ) +CMICmdArgValThreadGrp::~CMICmdArgValThreadGrp(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the value *this -// argument is looking for. -// Type: Overridden. -// Args: vwArgContext - (RW) The command's argument options string. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Parse the command's argument options string and try to extract the value *this +// argument is looking for. +// Type: Overridden. +// Args: vwArgContext - (RW) The command's argument options string. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgValThreadGrp::Validate( CMICmdArgContext & vwArgContext ) +bool +CMICmdArgValThreadGrp::Validate(CMICmdArgContext &vwArgContext) { - if( vwArgContext.IsEmpty() ) - return MIstatus::success; - - if( vwArgContext.GetNumberArgsPresent() == 1 ) - { - const CMIUtilString & rArg( vwArgContext.GetArgsLeftToParse() ); - if( IsArgThreadGrp( rArg ) && ExtractNumber( rArg ) ) - { - m_bFound = true; - m_bValid = true; - m_argValue = GetNumber(); - vwArgContext.RemoveArg( rArg ); - return MIstatus::success; - } - else - return MIstatus::failure; - } - - // More than one option... - const CMIUtilString::VecString_t vecOptions( vwArgContext.GetArgs() ); - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while( it != vecOptions.end() ) - { - const CMIUtilString & rArg( *it ); - if( IsArgThreadGrp( rArg ) && ExtractNumber( rArg ) ) - { - m_bFound = true; - - if( vwArgContext.RemoveArg( rArg ) ) - { - m_bValid = true; - m_argValue = GetNumber(); - return MIstatus::success; - } - else - return MIstatus::failure; - } - - // Next - ++it; - } - - return MIstatus::failure; + if (vwArgContext.IsEmpty()) + return MIstatus::success; + + if (vwArgContext.GetNumberArgsPresent() == 1) + { + const CMIUtilString &rArg(vwArgContext.GetArgsLeftToParse()); + if (IsArgThreadGrp(rArg) && ExtractNumber(rArg)) + { + m_bFound = true; + m_bValid = true; + m_argValue = GetNumber(); + vwArgContext.RemoveArg(rArg); + return MIstatus::success; + } + else + return MIstatus::failure; + } + + // More than one option... + const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) + { + const CMIUtilString &rArg(*it); + if (IsArgThreadGrp(rArg) && ExtractNumber(rArg)) + { + m_bFound = true; + + if (vwArgContext.RemoveArg(rArg)) + { + m_bValid = true; + m_argValue = GetNumber(); + return MIstatus::success; + } + else + return MIstatus::failure; + } + + // Next + ++it; + } + + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument. -// Type: Method. -// Args: vrTxt - (R) Some text. -// Return: bool - True = yes valid arg, false = no. -// Throws: None. +// Details: Examine the string and determine if it is a valid string type argument. +// Type: Method. +// Args: vrTxt - (R) Some text. +// Return: bool - True = yes valid arg, false = no. +// Throws: None. //-- -bool CMICmdArgValThreadGrp::IsArgThreadGrp( const CMIUtilString & vrTxt ) const +bool +CMICmdArgValThreadGrp::IsArgThreadGrp(const CMIUtilString &vrTxt) const { - // Look for i1 i2 i3.... - const MIint nPos = vrTxt.find_first_of( "i" ); - if( nPos != 0 ) - return false; - - const CMIUtilString strNum = vrTxt.substr( 1 ).c_str(); - if( !strNum.IsNumber() ) - return false; - - return true; + // Look for i1 i2 i3.... + const MIint nPos = vrTxt.find_first_of("i"); + if (nPos != 0) + return false; + + const CMIUtilString strNum = vrTxt.substr(1).c_str(); + if (!strNum.IsNumber()) + return false; + + return true; } //++ ------------------------------------------------------------------------------------ -// Details: Extract the thread group number from the thread group argument. -// Type: Method. -// Args: vrTxt - (R) Some text. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Extract the thread group number from the thread group argument. +// Type: Method. +// Args: vrTxt - (R) Some text. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdArgValThreadGrp::ExtractNumber( const CMIUtilString & vrTxt ) +bool +CMICmdArgValThreadGrp::ExtractNumber(const CMIUtilString &vrTxt) { - const CMIUtilString strNum = vrTxt.substr( 1 ).c_str(); - MIint64 nNumber = 0; - bool bOk = strNum.ExtractNumber( nNumber ); - if( bOk ) - { - m_nThreadGrp = static_cast< MIuint >( nNumber ); - } - - return bOk; + const CMIUtilString strNum = vrTxt.substr(1).c_str(); + MIint64 nNumber = 0; + bool bOk = strNum.ExtractNumber(nNumber); + if (bOk) + { + m_nThreadGrp = static_cast(nNumber); + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the thread group ID found in the argument. -// Type: Method. -// Args: None. -// Return: MIuint - Thread group ID. -// Throws: None. +// Details: Retrieve the thread group ID found in the argument. +// Type: Method. +// Args: None. +// Return: MIuint - Thread group ID. +// Throws: None. //-- -MIuint CMICmdArgValThreadGrp::GetNumber( void ) const +MIuint +CMICmdArgValThreadGrp::GetNumber(void) const { - return m_nThreadGrp; + return m_nThreadGrp; } - diff --git a/tools/lldb-mi/MICmdArgValThreadGrp.h b/tools/lldb-mi/MICmdArgValThreadGrp.h index 8903597dbca1..d82b89ff5017 100644 --- a/tools/lldb-mi/MICmdArgValThreadGrp.h +++ b/tools/lldb-mi/MICmdArgValThreadGrp.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdArgValThreadGrp.h +// File: MICmdArgValThreadGrp.h // -// Overview: CMICmdArgValThreadGrp interface. +// Overview: CMICmdArgValThreadGrp interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -28,39 +28,39 @@ class CMICmdArgContext; //++ ============================================================================ -// Details: MI common code class. Command argument class. Arguments object -// needing specialization derived from the CMICmdArgValBase class. -// An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching -// argument and so extract a value from it. Thread group looks like -// "i1" in the options text. -// Based on the Interpreter pattern. -// Gotchas: None. -// Authors: Illya Rudkin 15/04/2014. -// Changes: None. +// Details: MI common code class. Command argument class. Arguments object +// needing specialization derived from the CMICmdArgValBase class. +// An argument knows what type of argument it is and how it is to +// interpret the options (context) string to find and validate a matching +// argument and so extract a value from it. Thread group looks like +// "i1" in the options text. +// Based on the Interpreter pattern. +// Gotchas: None. +// Authors: Illya Rudkin 15/04/2014. +// Changes: None. //-- -class CMICmdArgValThreadGrp : public CMICmdArgValBaseTemplate< MIuint > +class CMICmdArgValThreadGrp : public CMICmdArgValBaseTemplate { -// Methods: -public: - /* ctor */ CMICmdArgValThreadGrp( void ); - /* ctor */ CMICmdArgValThreadGrp( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd ); - // - bool IsArgThreadGrp( const CMIUtilString & vrTxt ) const; - -// Overridden: -public: - // From CMICmdArgValBase - /* dtor */ virtual ~CMICmdArgValThreadGrp( void ); - // From CMICmdArgSet::IArg - virtual bool Validate( CMICmdArgContext & vArgContext ); + // Methods: + public: + /* ctor */ CMICmdArgValThreadGrp(void); + /* ctor */ CMICmdArgValThreadGrp(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); + // + bool IsArgThreadGrp(const CMIUtilString &vrTxt) const; -// Methods: -private: - bool ExtractNumber( const CMIUtilString & vrTxt ); - MIuint GetNumber( void ) const; + // Overridden: + public: + // From CMICmdArgValBase + /* dtor */ virtual ~CMICmdArgValThreadGrp(void); + // From CMICmdArgSet::IArg + virtual bool Validate(CMICmdArgContext &vArgContext); -// Attributes: -private: - MIuint m_nThreadGrp; + // Methods: + private: + bool ExtractNumber(const CMIUtilString &vrTxt); + MIuint GetNumber(void) const; + + // Attributes: + private: + MIuint m_nThreadGrp; }; diff --git a/tools/lldb-mi/MICmdBase.cpp b/tools/lldb-mi/MICmdBase.cpp index cedcba7e042f..d08dcb90f65f 100644 --- a/tools/lldb-mi/MICmdBase.cpp +++ b/tools/lldb-mi/MICmdBase.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdBase.cpp +// File: MICmdBase.cpp // -// Overview: CMICmdBase implementation. +// Overview: CMICmdBase implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -25,239 +25,253 @@ #include "MICmnLLDBDebugSessionInfo.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdBase constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdBase constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdBase::CMICmdBase( void ) -: m_pSelfCreatorFn( nullptr ) -, m_rLLDBDebugSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ) -, m_bHasResultRecordExtra( false ) +CMICmdBase::CMICmdBase(void) + : m_pSelfCreatorFn(nullptr) + , m_rLLDBDebugSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()) + , m_bHasResultRecordExtra(false) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdBase destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdBase destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdBase::~CMICmdBase( void ) +CMICmdBase::~CMICmdBase(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. -// Type: Overridden. -// Args: None. -// Return: SMICmdData & - *this command's present status/data/information. -// Throws: None. +// Details: The invoker requires this function. +// Type: Overridden. +// Args: None. +// Return: SMICmdData & - *this command's present status/data/information. +// Throws: None. //-- -const SMICmdData & CMICmdBase::GetCmdData( void ) const +const SMICmdData & +CMICmdBase::GetCmdData(void) const { - return m_cmdData; + return m_cmdData; } - + //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString & - *this command's current error description. -// Empty string indicates command status ok. -// Throws: None. +// Details: The invoker requires this function. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString & - *this command's current error description. +// Empty string indicates command status ok. +// Throws: None. //-- -const CMIUtilString & CMICmdBase::GetErrorDescription( void ) const +const CMIUtilString & +CMICmdBase::GetErrorDescription(void) const { - return m_strCurrentErrDescription; + return m_strCurrentErrDescription; } //++ ------------------------------------------------------------------------------------ -// Details: The CMICmdFactory requires this function. Retrieve the command and argument -// options description string. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString & - Command decription. -// Throws: None. +// Details: The CMICmdFactory requires this function. Retrieve the command and argument +// options description string. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString & - Command decription. +// Throws: None. //-- -const CMIUtilString & CMICmdBase::GetMiCmd( void ) const -{ - return m_strMiCmd; +const CMIUtilString & +CMICmdBase::GetMiCmd(void) const +{ + return m_strMiCmd; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. A command must be given working data and -// provide data about its status or provide information to other objects. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. A command must be given working data and +// provide data about its status or provide information to other objects. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdBase::SetCmdData( const SMICmdData & vCmdData ) +bool +CMICmdBase::SetCmdData(const SMICmdData &vCmdData) { - m_cmdData = vCmdData; + m_cmdData = vCmdData; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The command factory requires this function. The factory calls this function -// so it can obtain *this command's creation function. -// Type: Overridden. -// Args: None. -// Return: CMICmdFactory::CmdCreatorFnPtr - Function pointer. -// Throws: None. +// Details: The command factory requires this function. The factory calls this function +// so it can obtain *this command's creation function. +// Type: Overridden. +// Args: None. +// Return: CMICmdFactory::CmdCreatorFnPtr - Function pointer. +// Throws: None. //-- -CMICmdFactory::CmdCreatorFnPtr CMICmdBase::GetCmdCreatorFn( void ) const +CMICmdFactory::CmdCreatorFnPtr +CMICmdBase::GetCmdCreatorFn(void) const { - return m_pSelfCreatorFn; + return m_pSelfCreatorFn; } //++ ------------------------------------------------------------------------------------ -// Details: If a command is an event type (has callbacks registered with SBListener) it -// needs to inform the Invoker that it has finished its work so that the -// Invoker can tidy up and call the commands Acknowledge function (yes the -// command itself could call the Acknowledge itself but not doing that way). -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: If a command is an event type (has callbacks registered with SBListener) it +// needs to inform the Invoker that it has finished its work so that the +// Invoker can tidy up and call the commands Acknowledge function (yes the +// command itself could call the Acknowledge itself but not doing that way). +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMICmdBase::CmdFinishedTellInvoker( void ) const +void +CMICmdBase::CmdFinishedTellInvoker(void) const { - CMICmdInvoker::Instance().CmdExecuteFinished( const_cast< CMICmdBase & >( *this ) ); + CMICmdInvoker::Instance().CmdExecuteFinished(const_cast(*this)); } //++ ------------------------------------------------------------------------------------ -// Details: Returns the final version of the MI result record built up in the command's -// Acknowledge function. The one line text of MI result. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString & - MI text version of the MI result record. -// Throws: None. +// Details: Returns the final version of the MI result record built up in the command's +// Acknowledge function. The one line text of MI result. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString & - MI text version of the MI result record. +// Throws: None. //-- -const CMIUtilString & CMICmdBase::GetMIResultRecord( void ) const +const CMIUtilString & +CMICmdBase::GetMIResultRecord(void) const { - return m_miResultRecord.GetString(); + return m_miResultRecord.GetString(); } - + //++ ------------------------------------------------------------------------------------ -// Details: Retrieve from the command additional MI result to its 1 line response. -// Because of using LLDB addtional 'fake'/hack output is sometimes required to -// help the driver client operate i.e. Eclipse. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString & - MI text version of the MI result record. -// Throws: None. +// Details: Retrieve from the command additional MI result to its 1 line response. +// Because of using LLDB addtional 'fake'/hack output is sometimes required to +// help the driver client operate i.e. Eclipse. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString & - MI text version of the MI result record. +// Throws: None. //-- -const CMIUtilString & CMICmdBase::GetMIResultRecordExtra( void ) const +const CMIUtilString & +CMICmdBase::GetMIResultRecordExtra(void) const { - return m_miResultRecordExtra; + return m_miResultRecordExtra; } //++ ------------------------------------------------------------------------------------ -// Details: Hss *this command got additional MI result to its 1 line response. -// Because of using LLDB addtional 'fake'/hack output is sometimes required to -// help the driver client operate i.e. Eclipse. -// Type: Overridden. -// Args: None. -// Return: bool - True = Yes have additional MI output, false = no nothing extra. -// Throws: None. +// Details: Hss *this command got additional MI result to its 1 line response. +// Because of using LLDB addtional 'fake'/hack output is sometimes required to +// help the driver client operate i.e. Eclipse. +// Type: Overridden. +// Args: None. +// Return: bool - True = Yes have additional MI output, false = no nothing extra. +// Throws: None. //-- -bool CMICmdBase::HasMIResultRecordExtra( void ) const +bool +CMICmdBase::HasMIResultRecordExtra(void) const { - return m_bHasResultRecordExtra; + return m_bHasResultRecordExtra; } //++ ------------------------------------------------------------------------------------ -// Details: Short cut function to enter error information into the command's metadata -// object and set the command's error status. -// Type: Method. -// Args: rErrMsg - (R) Error description. -// Return: None. -// Throws: None. +// Details: Short cut function to enter error information into the command's metadata +// object and set the command's error status. +// Type: Method. +// Args: rErrMsg - (R) Error description. +// Return: None. +// Throws: None. //-- -void CMICmdBase::SetError( const CMIUtilString & rErrMsg ) +void +CMICmdBase::SetError(const CMIUtilString &rErrMsg) { - m_cmdData.bCmdValid = false; - m_cmdData.strErrorDescription = rErrMsg; - m_cmdData.bCmdExecutedSuccessfully = false; - - const CMICmnMIValueResult valueResult( "msg", CMICmnMIValueConst( rErrMsg ) ); - const CMICmnMIResultRecord miResultRecord( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, valueResult ); - m_miResultRecord = miResultRecord; - m_cmdData.strMiCmdResultRecord = miResultRecord.GetString(); + m_cmdData.bCmdValid = false; + m_cmdData.strErrorDescription = rErrMsg; + m_cmdData.bCmdExecutedSuccessfully = false; + + const CMICmnMIValueResult valueResult("msg", CMICmnMIValueConst(rErrMsg)); + const CMICmnMIResultRecord miResultRecord(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, valueResult); + m_miResultRecord = miResultRecord; + m_cmdData.strMiCmdResultRecord = miResultRecord.GetString(); } //++ ------------------------------------------------------------------------------------ -// Details: Ask a command to provide its unique identifier. -// Type: Method. -// Args: A unique identifier for this command class. -// Return: None. -// Throws: None. +// Details: Ask a command to provide its unique identifier. +// Type: Method. +// Args: A unique identifier for this command class. +// Return: None. +// Throws: None. //-- -MIuint CMICmdBase::GetGUID( void ) +MIuint +CMICmdBase::GetGUID(void) { - MIuint64 vptr = reinterpret_cast< MIuint64 >( this ); - MIuint id = (vptr ) & 0xFFFFFFFF; - id ^= (vptr >> 32) & 0xFFFFFFFF; + MIuint64 vptr = reinterpret_cast(this); + MIuint id = (vptr)&0xFFFFFFFF; + id ^= (vptr >> 32) & 0xFFFFFFFF; - return id; + return id; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdBase::ParseArgs( void ) -{ - // Do nothing - override to implement +bool +CMICmdBase::ParseArgs(void) +{ + // Do nothing - override to implement - return MIstatus::success; + return MIstatus::success; } - + //++ ------------------------------------------------------------------------------------ -// Details: Having previously given CMICmdArgSet m_setCmdArgs all the argument or option -// definitions for the command to handle proceed to parse and validate the -// command's options text for those arguments and extract the values for each if -// any. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Having previously given CMICmdArgSet m_setCmdArgs all the argument or option +// definitions for the command to handle proceed to parse and validate the +// command's options text for those arguments and extract the values for each if +// any. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdBase::ParseValidateCmdOptions( void ) +bool +CMICmdBase::ParseValidateCmdOptions(void) { - CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption ); - if( m_setCmdArgs.Validate( m_cmdData.strMiCmd, argCntxt ) ) - return MIstatus::success; - - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_ARGS ), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str() ) ); + CMICmdArgContext argCntxt(m_cmdData.strMiCmdOption); + if (m_setCmdArgs.Validate(m_cmdData.strMiCmd, argCntxt)) + return MIstatus::success; + + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_ARGS), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str())); - return MIstatus::failure; + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: If the MI Driver is not operating via a client i.e. Eclipse but say operating -// on a executable passed in as a argument to the drive then what should the driver -// do on a command failing? Either continue operating or exit the application. -// Override this function where a command failure cannot allow the driver to -// continue operating. -// Type: Overrideable. -// Args: None. -// Return: bool - True = Fatal if command fails, false = can continue if command fails. -// Throws: None. +// Details: If the MI Driver is not operating via a client i.e. Eclipse but say operating +// on a executable passed in as a argument to the drive then what should the driver +// do on a command failing? Either continue operating or exit the application. +// Override this function where a command failure cannot allow the driver to +// continue operating. +// Type: Overrideable. +// Args: None. +// Return: bool - True = Fatal if command fails, false = can continue if command fails. +// Throws: None. //-- -bool CMICmdBase::GetExitAppOnCommandFailure( void ) const +bool +CMICmdBase::GetExitAppOnCommandFailure(void) const { - return false; + return false; } diff --git a/tools/lldb-mi/MICmdBase.h b/tools/lldb-mi/MICmdBase.h index b05e97d2082d..c2a8fe030310 100644 --- a/tools/lldb-mi/MICmdBase.h +++ b/tools/lldb-mi/MICmdBase.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdBase.h +// File: MICmdBase.h // -// Overview: CMICmdBase interface. +// Overview: CMICmdBase interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -35,122 +35,124 @@ class CMICmnLLDBDebugSessionInfo; //++ ============================================================================ -// Details: MI command base class. MI commands derive from this base class. -// The Command Factory creates command objects and passes them to the -// Command Invoker. The Invoker takes ownersip of any commands created -// which means it is the only object to delete them when a command is -// finished working. Commands do not delete themselves. -// There are two types of command implicitly defined by the state of -// the m_bWaitForEventFromSBDebugger flag. There is the event type -// command which registers (command fn) callbacks with the SBListener -// does some work then wakes up again when called back, does more work -// perhaps, ends, then the Invoker calls the command's Acknowledge -// function. The other type of command is one that just does some work, -// ends, then the Invoker calls the command's Acknowledge function. No -// events set up. -// A command's Execute(), Acknowledge() and event callback functions are -// carried out in the main thread. -// A command may use the argument derived object classes (CMICmdArgValBase) -// to factor handling and parsing of different types of arguments -// presented to a command. A command will produce an error should it -// be presented with arguments or options it does not understand. -// Gotchas: None. -// Authors: Illya Rudkin 18/02/2014. -// Changes: None. +// Details: MI command base class. MI commands derive from this base class. +// The Command Factory creates command objects and passes them to the +// Command Invoker. The Invoker takes ownersip of any commands created +// which means it is the only object to delete them when a command is +// finished working. Commands do not delete themselves. +// There are two types of command implicitly defined by the state of +// the m_bWaitForEventFromSBDebugger flag. There is the event type +// command which registers (command fn) callbacks with the SBListener +// does some work then wakes up again when called back, does more work +// perhaps, ends, then the Invoker calls the command's Acknowledge +// function. The other type of command is one that just does some work, +// ends, then the Invoker calls the command's Acknowledge function. No +// events set up. +// A command's Execute(), Acknowledge() and event callback functions are +// carried out in the main thread. +// A command may use the argument derived object classes (CMICmdArgValBase) +// to factor handling and parsing of different types of arguments +// presented to a command. A command will produce an error should it +// be presented with arguments or options it does not understand. +// Gotchas: None. +// Authors: Illya Rudkin 18/02/2014. +// Changes: None. //-- -class CMICmdBase -: public CMICmnBase -, public CMICmdInvoker::ICmd -, public CMICmdFactory::ICmd +class CMICmdBase : public CMICmnBase, public CMICmdInvoker::ICmd, public CMICmdFactory::ICmd { -// Methods: -public: - /* ctor */ CMICmdBase( void ); + // Methods: + public: + /* ctor */ CMICmdBase(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual const SMICmdData & GetCmdData( void ) const; - virtual const CMIUtilString & GetErrorDescription( void ) const; - virtual bool SetCmdData( const SMICmdData & vCmdData ); - virtual void CmdFinishedTellInvoker( void ) const; - virtual const CMIUtilString & GetMIResultRecord( void ) const; - virtual const CMIUtilString & GetMIResultRecordExtra( void ) const; - virtual bool HasMIResultRecordExtra( void ) const; - virtual bool ParseArgs( void ); - // From CMICmdFactory::ICmd - virtual const CMIUtilString & GetMiCmd( void ) const; - virtual CMICmdFactory::CmdCreatorFnPtr GetCmdCreatorFn( void ) const; + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual const SMICmdData &GetCmdData(void) const; + virtual const CMIUtilString &GetErrorDescription(void) const; + virtual bool SetCmdData(const SMICmdData &vCmdData); + virtual void CmdFinishedTellInvoker(void) const; + virtual const CMIUtilString &GetMIResultRecord(void) const; + virtual const CMIUtilString &GetMIResultRecordExtra(void) const; + virtual bool HasMIResultRecordExtra(void) const; + virtual bool ParseArgs(void); + // From CMICmdFactory::ICmd + virtual const CMIUtilString &GetMiCmd(void) const; + virtual CMICmdFactory::CmdCreatorFnPtr GetCmdCreatorFn(void) const; - virtual MIuint GetGUID( void ); + virtual MIuint GetGUID(void); -// Overrideable: -public: - /* dtor */ virtual ~CMICmdBase( void ); - virtual bool GetExitAppOnCommandFailure( void ) const; + // Overrideable: + public: + /* dtor */ virtual ~CMICmdBase(void); + virtual bool GetExitAppOnCommandFailure(void) const; -// Methods: -protected: - void SetError( const CMIUtilString & rErrMsg ); - template< class T > - T * GetOption( const CMIUtilString & vStrOptionName ); - bool ParseValidateCmdOptions( void ); - -// Attributes: -protected: - CMICmdFactory::CmdCreatorFnPtr m_pSelfCreatorFn; - CMIUtilString m_strCurrentErrDescription; // Reason for Execute or Acknowledge function failure - SMICmdData m_cmdData; // Holds information/status of *this command. Used by other MI code to report or determine state of a command. - bool m_bWaitForEventFromSBDebugger; // True = yes event type command wait, false = command calls Acknowledge() straight after Execute() no waiting - CMIUtilString m_strMiCmd; // The MI text identifying *this command i.e. 'break-insert' - CMICmnMIResultRecord m_miResultRecord; // This is completed in the Acknowledge() function and returned to the Command Invoker to proceed stdout output. Each command forms 1 response to its input. - CMIUtilString m_miResultRecordExtra; // This is completed in the Acknowledge() function and returned to the Command Invoker to proceed stdout output. Hack command produce more response text to help the client because of using LLDB - CMICmnLLDBDebugSessionInfo & m_rLLDBDebugSessionInfo; // Access to command sharing information or data across any and all command based derived classes. - bool m_bHasResultRecordExtra; // True = Yes command produced additional MI output to its 1 line response, false = no extra MI output formed. - CMICmdArgSet m_setCmdArgs; // The list of arguments *this command needs to parse from the options string to carry out work. + // Methods: + protected: + void SetError(const CMIUtilString &rErrMsg); + template T *GetOption(const CMIUtilString &vStrOptionName); + bool ParseValidateCmdOptions(void); + + // Attributes: + protected: + CMICmdFactory::CmdCreatorFnPtr m_pSelfCreatorFn; + CMIUtilString m_strCurrentErrDescription; // Reason for Execute or Acknowledge function failure + SMICmdData m_cmdData; // Holds information/status of *this command. Used by other MI code to report or determine state of a command. + bool m_bWaitForEventFromSBDebugger; // True = yes event type command wait, false = command calls Acknowledge() straight after Execute() + // no waiting + CMIUtilString m_strMiCmd; // The MI text identifying *this command i.e. 'break-insert' + CMICmnMIResultRecord m_miResultRecord; // This is completed in the Acknowledge() function and returned to the Command Invoker to proceed + // stdout output. Each command forms 1 response to its input. + CMIUtilString m_miResultRecordExtra; // This is completed in the Acknowledge() function and returned to the Command Invoker to proceed + // stdout output. Hack command produce more response text to help the client because of using LLDB + CMICmnLLDBDebugSessionInfo & + m_rLLDBDebugSessionInfo; // Access to command sharing information or data across any and all command based derived classes. + bool m_bHasResultRecordExtra; // True = Yes command produced additional MI output to its 1 line response, false = no extra MI output + // formed. + CMICmdArgSet m_setCmdArgs; // The list of arguments *this command needs to parse from the options string to carry out work. }; //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the command argument or option object pointer so that it can be -// examined. If the option found and valid get the value (number, string or list -// - see CMICmdArgValBase class) from it to use with the command's decision -// making. If the argument is not found the command's error description is set -// describing the error condition. -// Type: Template method. -// Args: vStrOptionName - (R) The text name of the argument or option to search for in -// the list of the command's possible arguments or options. -// Return: T * - CMICmdArgValBase derived object. -// - NULL = function has failed, unable to retrieve the option/arg object. -// Throws: None. +// Details: Retrieve the command argument or option object pointer so that it can be +// examined. If the option found and valid get the value (number, string or list +// - see CMICmdArgValBase class) from it to use with the command's decision +// making. If the argument is not found the command's error description is set +// describing the error condition. +// Type: Template method. +// Args: vStrOptionName - (R) The text name of the argument or option to search for in +// the list of the command's possible arguments or options. +// Return: T * - CMICmdArgValBase derived object. +// - NULL = function has failed, unable to retrieve the option/arg object. +// Throws: None. //-- -template< class T > -T * CMICmdBase::GetOption( const CMIUtilString & vStrOptionName ) +template +T * +CMICmdBase::GetOption(const CMIUtilString &vStrOptionName) { - CMICmdArgValBase * pPtrBase = nullptr; - if( !m_setCmdArgs.GetArg( vStrOptionName, pPtrBase ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), vStrOptionName.c_str() ) ); - return nullptr; - } + CMICmdArgValBase *pPtrBase = nullptr; + if (!m_setCmdArgs.GetArg(vStrOptionName, pPtrBase)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), vStrOptionName.c_str())); + return nullptr; + } - return static_cast< T * >( pPtrBase ); + return static_cast(pPtrBase); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the command argument or option object pointer using template function -// CMICmdBase::GetOption(). Should the argument (by name) not be found the -// command will exit with a failure (set in GetOption()). -// Type: Preprocessor macro. -// Args: a - (R) The actual variable's name. -// b - (R) The type of variable (appended to CMICmdArgVal i.e. CMICmdArgValString). -// c - (R) The text name of the argument or option to search for in the list of -// the command's possible arguments or options. -// Return: T * - CMICmdArgValBase derived object. -// - NULL = function has failed, unable to retrieve the option/arg object. -// Throws: None. +// Details: Retrieve the command argument or option object pointer using template function +// CMICmdBase::GetOption(). Should the argument (by name) not be found the +// command will exit with a failure (set in GetOption()). +// Type: Preprocessor macro. +// Args: a - (R) The actual variable's name. +// b - (R) The type of variable (appended to CMICmdArgVal i.e. CMICmdArgValString). +// c - (R) The text name of the argument or option to search for in the list of +// the command's possible arguments or options. +// Return: T * - CMICmdArgValBase derived object. +// - NULL = function has failed, unable to retrieve the option/arg object. +// Throws: None. //-- -#define CMICMDBASE_GETOPTION( a, b, c ) \ - CMICmdArgVal##b * a = CMICmdBase::GetOption< CMICmdArgVal##b >( c );\ - if( a == nullptr ) \ - return MIstatus::failure; +#define CMICMDBASE_GETOPTION(a, b, c) \ + CMICmdArgVal##b *a = CMICmdBase::GetOption(c); \ + if (a == nullptr) \ + return MIstatus::failure; // This comment is to stop compile warning for #define diff --git a/tools/lldb-mi/MICmdCmd.cpp b/tools/lldb-mi/MICmdCmd.cpp index 3c6d52b24769..50f651f634f6 100644 --- a/tools/lldb-mi/MICmdCmd.cpp +++ b/tools/lldb-mi/MICmdCmd.cpp @@ -8,93 +8,96 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmd.cpp +// File: MICmdCmd.cpp // -// Overview: CMICmdCmdEnablePrettyPrinting implementation. -// CMICmdCmdSource implementation. +// Overview: CMICmdCmdEnablePrettyPrinting implementation. +// CMICmdCmdSource implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: #include "MICmdCmd.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdEnablePrettyPrinting constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdEnablePrettyPrinting constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdEnablePrettyPrinting::CMICmdCmdEnablePrettyPrinting( void ) +CMICmdCmdEnablePrettyPrinting::CMICmdCmdEnablePrettyPrinting(void) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "enable-pretty-printing"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdEnablePrettyPrinting::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "enable-pretty-printing"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdEnablePrettyPrinting::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdEnablePrettyPrinting destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdEnablePrettyPrinting destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdEnablePrettyPrinting::~CMICmdCmdEnablePrettyPrinting( void ) +CMICmdCmdEnablePrettyPrinting::~CMICmdCmdEnablePrettyPrinting(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdEnablePrettyPrinting::Execute( void ) +bool +CMICmdCmdEnablePrettyPrinting::Execute(void) { - // Do nothing - return MIstatus::success; + // Do nothing + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdEnablePrettyPrinting::Acknowledge( void ) +bool +CMICmdCmdEnablePrettyPrinting::Acknowledge(void) { - const CMICmnMIValueConst miValueConst( "0" ); - const CMICmnMIValueResult miValueResult( "supported", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + const CMICmnMIValueConst miValueConst("0"); + const CMICmnMIValueResult miValueResult("supported", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdEnablePrettyPrinting::CreateSelf( void ) +CMICmdBase * +CMICmdCmdEnablePrettyPrinting::CreateSelf(void) { - return new CMICmdCmdEnablePrettyPrinting(); + return new CMICmdCmdEnablePrettyPrinting(); } //--------------------------------------------------------------------------------------- @@ -102,73 +105,76 @@ CMICmdBase * CMICmdCmdEnablePrettyPrinting::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdSource constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdSource constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdSource::CMICmdCmdSource( void ) +CMICmdCmdSource::CMICmdCmdSource(void) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "source"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdSource::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "source"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdSource::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdSource destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdSource destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdSource::~CMICmdCmdSource( void ) +CMICmdCmdSource::~CMICmdCmdSource(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdSource::Execute( void ) +bool +CMICmdCmdSource::Execute(void) { - // Do nothing - return MIstatus::success; + // Do nothing + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdSource::Acknowledge( void ) +bool +CMICmdCmdSource::Acknowledge(void) { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdSource::CreateSelf( void ) +CMICmdBase * +CMICmdCmdSource::CreateSelf(void) { - return new CMICmdCmdSource(); + return new CMICmdCmdSource(); } diff --git a/tools/lldb-mi/MICmdCmd.h b/tools/lldb-mi/MICmdCmd.h index c2ab6896e689..b51318fa9dff 100644 --- a/tools/lldb-mi/MICmdCmd.h +++ b/tools/lldb-mi/MICmdCmd.h @@ -8,30 +8,30 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmd.h +// File: MICmdCmd.h // -// Overview: CMICmdCmdEnablePrettyPrinting interface. -// CMICmdCmdSource interface. +// Overview: CMICmdCmdEnablePrettyPrinting interface. +// CMICmdCmdSource interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- -/* +/* MI commands implemented are: - See MICmdCommands.cpp + See MICmdCommands.cpp */ #pragma once @@ -47,58 +47,57 @@ MI commands implemented are: #include "MICmnMIValueList.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "enable-pretty-printing". -// Enables Python base pretty printing. -// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html -// Gotchas: None. -// Authors: Illya Rudkin 03/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "enable-pretty-printing". +// Enables Python base pretty printing. +// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html +// Gotchas: None. +// Authors: Illya Rudkin 03/03/2014. +// Changes: None. //-- class CMICmdCmdEnablePrettyPrinting : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdEnablePrettyPrinting( void ); + // Methods: + public: + /* ctor */ CMICmdCmdEnablePrettyPrinting(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdEnablePrettyPrinting( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdEnablePrettyPrinting(void); }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "source". -// Gotchas: None. -// Authors: Illya Rudkin 05/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "source". +// Gotchas: None. +// Authors: Illya Rudkin 05/03/2014. +// Changes: None. //-- -class CMICmdCmdSource - : public CMICmdBase +class CMICmdCmdSource : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdSource( void ); + // Methods: + public: + /* ctor */ CMICmdCmdSource(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdSource( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdSource(void); }; diff --git a/tools/lldb-mi/MICmdCmdBreak.cpp b/tools/lldb-mi/MICmdCmdBreak.cpp index f0e9acfe9082..c338cf0a363d 100644 --- a/tools/lldb-mi/MICmdCmdBreak.cpp +++ b/tools/lldb-mi/MICmdCmdBreak.cpp @@ -8,20 +8,20 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdBreak.cpp +// File: MICmdCmdBreak.cpp // -// Overview: CMICmdCmdBreakInsert implementation. -// CMICmdCmdBreakDelete implementation. -// CMICmdCmdBreakDisable implementation. -// CMICmdCmdBreakEnable implementation. -// CMICmdCmdBreakAfter implementation. -// CMICmdCmdBreakCondition implementation. +// Overview: CMICmdCmdBreakInsert implementation. +// CMICmdCmdBreakDelete implementation. +// CMICmdCmdBreakDisable implementation. +// CMICmdCmdBreakEnable implementation. +// CMICmdCmdBreakAfter implementation. +// CMICmdCmdBreakCondition implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third Party Headers: @@ -44,308 +44,325 @@ #include "MICmnStreamStdout.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdBreakInsert constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdBreakInsert constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdBreakInsert::CMICmdCmdBreakInsert( void ) -: m_bBrkPtIsTemp( false ) -, m_bBrkPtIsPending( false ) -, m_nBrkPtIgnoreCount( 0 ) -, m_bBrkPtEnabled( false ) -, m_bBrkPtCondition( false ) -, m_bBrkPtThreadId( false ) -, m_nBrkPtThreadId( 0 ) -, m_constStrArgNamedTempBrkPt( "t" ) -, m_constStrArgNamedHWBrkPt( "h" ) -, m_constStrArgNamedPendinfBrkPt( "f" ) -, m_constStrArgNamedDisableBrkPt( "d" ) -, m_constStrArgNamedTracePt( "a" ) -, m_constStrArgNamedConditionalBrkPt( "c" ) -, m_constStrArgNamedInoreCnt( "i" ) -, m_constStrArgNamedRestrictBrkPtToThreadId( "p" ) -, m_constStrArgNamedLocation( "location" ) -, m_constStrArgNamedThreadGroup( "thread-group" ) +CMICmdCmdBreakInsert::CMICmdCmdBreakInsert(void) + : m_bBrkPtIsTemp(false) + , m_bBrkPtIsPending(false) + , m_nBrkPtIgnoreCount(0) + , m_bBrkPtEnabled(false) + , m_bBrkPtCondition(false) + , m_bBrkPtThreadId(false) + , m_nBrkPtThreadId(0) + , m_constStrArgNamedTempBrkPt("t") + , m_constStrArgNamedHWBrkPt("h") + , m_constStrArgNamedPendinfBrkPt("f") + , m_constStrArgNamedDisableBrkPt("d") + , m_constStrArgNamedTracePt("a") + , m_constStrArgNamedConditionalBrkPt("c") + , m_constStrArgNamedInoreCnt("i") + , m_constStrArgNamedRestrictBrkPtToThreadId("p") + , m_constStrArgNamedLocation("location") + , m_constStrArgNamedThreadGroup("thread-group") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "break-insert"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdBreakInsert::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "break-insert"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdBreakInsert::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdBreakInsert destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdBreakInsert destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdBreakInsert::~CMICmdCmdBreakInsert( void ) +CMICmdCmdBreakInsert::~CMICmdCmdBreakInsert(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakInsert::ParseArgs( void ) +bool +CMICmdCmdBreakInsert::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedTempBrkPt, false, true )) ); - //Not implemented bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedHWBrkPt, false, false ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedPendinfBrkPt, false, true, CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedDisableBrkPt, false, false ) ) ); - //Not implemented bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedTracePt, false, false ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedConditionalBrkPt, false, true, CMICmdArgValListBase::eArgValType_StringQuoted, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedInoreCnt, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedRestrictBrkPtToThreadId, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedLocation, false, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedThreadGroup, false, true, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedTempBrkPt, false, true))); + // Not implemented bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedHWBrkPt, false, false ) ) ); + bOk = bOk && + m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedPendinfBrkPt, false, true, + CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedDisableBrkPt, false, false))); + // Not implemented bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedTracePt, false, false ) ) ); + bOk = bOk && + m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedConditionalBrkPt, false, true, + CMICmdArgValListBase::eArgValType_StringQuoted, 1))); + bOk = bOk && + m_setCmdArgs.Add( + *(new CMICmdArgValOptionShort(m_constStrArgNamedInoreCnt, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && + m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedRestrictBrkPtToThreadId, false, true, + CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedLocation, false, true))); + bOk = bOk && + m_setCmdArgs.Add( + *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGroup, false, true, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakInsert::Execute( void ) +bool +CMICmdCmdBreakInsert::Execute(void) { - CMICMDBASE_GETOPTION( pArgTempBrkPt, OptionShort, m_constStrArgNamedTempBrkPt ); - CMICMDBASE_GETOPTION( pArgThreadGroup, OptionLong, m_constStrArgNamedThreadGroup ); - CMICMDBASE_GETOPTION( pArgLocation, String, m_constStrArgNamedLocation ); - CMICMDBASE_GETOPTION( pArgIgnoreCnt, OptionShort, m_constStrArgNamedInoreCnt ); - CMICMDBASE_GETOPTION( pArgPendingBrkPt, OptionShort, m_constStrArgNamedPendinfBrkPt ); - CMICMDBASE_GETOPTION( pArgDisableBrkPt, OptionShort, m_constStrArgNamedDisableBrkPt ); - CMICMDBASE_GETOPTION( pArgConditionalBrkPt, OptionShort, m_constStrArgNamedConditionalBrkPt ); - CMICMDBASE_GETOPTION( pArgRestrictBrkPtToThreadId, OptionShort, m_constStrArgNamedRestrictBrkPtToThreadId ); - - m_bBrkPtEnabled = !pArgDisableBrkPt->GetFound(); - m_bBrkPtIsTemp = pArgTempBrkPt->GetFound(); - m_bHaveArgOptionThreadGrp = pArgThreadGroup->GetFound(); - if( m_bHaveArgOptionThreadGrp ) - { - MIuint nThreadGrp = 0; - pArgThreadGroup->GetExpectedOption< CMICmdArgValThreadGrp, MIuint >( nThreadGrp ); - m_strArgOptionThreadGrp = CMIUtilString::Format( "i%d", nThreadGrp ); - } - m_bBrkPtIsPending = pArgPendingBrkPt->GetFound(); - if( pArgLocation->GetFound() ) - m_brkName = pArgLocation->GetValue(); - else if( m_bBrkPtIsPending ) - { - pArgPendingBrkPt->GetExpectedOption< CMICmdArgValString, CMIUtilString >( m_brkName ); - } - if( pArgIgnoreCnt->GetFound() ) - { - pArgIgnoreCnt->GetExpectedOption< CMICmdArgValNumber, MIuint >( m_nBrkPtIgnoreCount ); - } - m_bBrkPtCondition = pArgConditionalBrkPt->GetFound(); - if( m_bBrkPtCondition ) - { - pArgConditionalBrkPt->GetExpectedOption< CMICmdArgValString, CMIUtilString >( m_brkPtCondition ); - } - m_bBrkPtThreadId = pArgRestrictBrkPtToThreadId->GetFound(); - if( m_bBrkPtCondition ) - { - pArgRestrictBrkPtToThreadId->GetExpectedOption< CMICmdArgValNumber, MIuint >( m_nBrkPtThreadId ); - } - - // Determine if break on a file line or at a function - BreakPoint_e eBrkPtType = eBreakPoint_NotDefineYet; - const CMIUtilString cColon = ":"; - CMIUtilString fileName; - MIuint nFileLine = 0; - CMIUtilString strFileFn; - const MIint nPosColon = m_brkName.find( cColon ); - if( nPosColon != (MIint) std::string::npos ) - { - CMIUtilString::VecString_t vecFileAndLocation; - const MIuint nSplits = m_brkName.Split( cColon, vecFileAndLocation ); MIunused( nSplits ); - if( vecFileAndLocation.size() != 2 ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_LOCATION_FORMAT ), m_cmdData.strMiCmd.c_str(), m_brkName.c_str() ) ); - return MIstatus::failure; - } - fileName = vecFileAndLocation.at( 0 ); - const CMIUtilString & rStrLineOrFn( vecFileAndLocation.at( 1 ) ); - if( rStrLineOrFn.empty() ) - eBrkPtType = eBreakPoint_ByName; - else - { - MIint64 nValue = 0; - if( rStrLineOrFn.ExtractNumber( nValue ) ) - { - nFileLine = static_cast< MIuint >( nValue ); - eBrkPtType = eBreakPoint_ByFileLine; - } - else - { - strFileFn = rStrLineOrFn; - eBrkPtType = eBreakPoint_ByFileFn; - } - } - } - - // Determine if break defined as an address - lldb::addr_t nAddress = 0; - if( eBrkPtType == eBreakPoint_NotDefineYet ) - { - MIint64 nValue = 0; - if( m_brkName.ExtractNumber( nValue ) ) - { - nAddress = static_cast< lldb::addr_t >( nValue ); - eBrkPtType = eBreakPoint_ByAddress; - } - } - - // Break defined as an function - if( eBrkPtType == eBreakPoint_NotDefineYet ) - { - eBrkPtType = eBreakPoint_ByName; - } - - // Ask LLDB to create a breakpoint - bool bOk = MIstatus::success; - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBTarget & rTarget = rSessionInfo.m_lldbTarget; - switch( eBrkPtType ) - { - case eBreakPoint_ByAddress: - m_brkPt = rTarget.BreakpointCreateByAddress( nAddress ); - break; - case eBreakPoint_ByFileFn: - m_brkPt = rTarget.BreakpointCreateByName( strFileFn.c_str(), fileName.c_str() ); - break; - case eBreakPoint_ByFileLine: - m_brkPt = rTarget.BreakpointCreateByLocation( fileName.c_str(), nFileLine ); - break; - case eBreakPoint_ByName: - m_brkPt = rTarget.BreakpointCreateByName( m_brkName.c_str(), rTarget.GetExecutable().GetFilename() ); - break; - case eBreakPoint_count: - case eBreakPoint_NotDefineYet: - case eBreakPoint_Invalid: - bOk = MIstatus::failure; - break; - } - - if( bOk ) - { - m_brkPt.SetEnabled( m_bBrkPtEnabled ); - m_brkPt.SetIgnoreCount( m_nBrkPtIgnoreCount ); - if( m_bBrkPtCondition ) - m_brkPt.SetCondition( m_brkPtCondition.c_str() ); - if( m_bBrkPtThreadId ) - m_brkPt.SetThreadID( m_nBrkPtThreadId ); - if( !m_brkPt.IsValid() ) - m_bBrkPtIsPending = pArgPendingBrkPt->GetFound(); - } - - // CODETAG_LLDB_BREAKPOINT_CREATION - // This is in the main thread - // Record break point information to be by LLDB event handler function - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; - sBrkPtInfo.m_id = m_brkPt.GetID(); - sBrkPtInfo.m_bDisp = m_bBrkPtIsTemp; - sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled; - sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp; - sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp; - sBrkPtInfo.m_strOrigLoc = m_brkName; - sBrkPtInfo.m_nIgnore = m_nBrkPtIgnoreCount; - sBrkPtInfo.m_bPending = m_bBrkPtIsPending; - sBrkPtInfo.m_bCondition = m_bBrkPtCondition; - sBrkPtInfo.m_strCondition = m_brkPtCondition; - sBrkPtInfo.m_bBrkPtThreadId = m_bBrkPtThreadId; - sBrkPtInfo.m_nBrkPtThreadId = m_nBrkPtThreadId; - bOk = bOk && rSessionInfo.RecordBrkPtInfo( m_brkPt.GetID(), sBrkPtInfo ); - - if( !bOk ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), m_brkName.c_str() ) ); - return MIstatus::failure; - } - - // CODETAG_LLDB_BRKPT_ID_MAX - if( m_brkPt.GetID() > (lldb::break_id_t) rSessionInfo.m_nBrkPointCntMax ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_CNT_EXCEEDED ), m_cmdData.strMiCmd.c_str(), rSessionInfo.m_nBrkPointCntMax, m_brkName.c_str() ) ); - return MIstatus::failure; - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgTempBrkPt, OptionShort, m_constStrArgNamedTempBrkPt); + CMICMDBASE_GETOPTION(pArgThreadGroup, OptionLong, m_constStrArgNamedThreadGroup); + CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgNamedLocation); + CMICMDBASE_GETOPTION(pArgIgnoreCnt, OptionShort, m_constStrArgNamedInoreCnt); + CMICMDBASE_GETOPTION(pArgPendingBrkPt, OptionShort, m_constStrArgNamedPendinfBrkPt); + CMICMDBASE_GETOPTION(pArgDisableBrkPt, OptionShort, m_constStrArgNamedDisableBrkPt); + CMICMDBASE_GETOPTION(pArgConditionalBrkPt, OptionShort, m_constStrArgNamedConditionalBrkPt); + CMICMDBASE_GETOPTION(pArgRestrictBrkPtToThreadId, OptionShort, m_constStrArgNamedRestrictBrkPtToThreadId); + + m_bBrkPtEnabled = !pArgDisableBrkPt->GetFound(); + m_bBrkPtIsTemp = pArgTempBrkPt->GetFound(); + m_bHaveArgOptionThreadGrp = pArgThreadGroup->GetFound(); + if (m_bHaveArgOptionThreadGrp) + { + MIuint nThreadGrp = 0; + pArgThreadGroup->GetExpectedOption(nThreadGrp); + m_strArgOptionThreadGrp = CMIUtilString::Format("i%d", nThreadGrp); + } + m_bBrkPtIsPending = pArgPendingBrkPt->GetFound(); + if (pArgLocation->GetFound()) + m_brkName = pArgLocation->GetValue(); + else if (m_bBrkPtIsPending) + { + pArgPendingBrkPt->GetExpectedOption(m_brkName); + } + if (pArgIgnoreCnt->GetFound()) + { + pArgIgnoreCnt->GetExpectedOption(m_nBrkPtIgnoreCount); + } + m_bBrkPtCondition = pArgConditionalBrkPt->GetFound(); + if (m_bBrkPtCondition) + { + pArgConditionalBrkPt->GetExpectedOption(m_brkPtCondition); + } + m_bBrkPtThreadId = pArgRestrictBrkPtToThreadId->GetFound(); + if (m_bBrkPtCondition) + { + pArgRestrictBrkPtToThreadId->GetExpectedOption(m_nBrkPtThreadId); + } + + // Determine if break on a file line or at a function + BreakPoint_e eBrkPtType = eBreakPoint_NotDefineYet; + const CMIUtilString cColon = ":"; + CMIUtilString fileName; + MIuint nFileLine = 0; + CMIUtilString strFileFn; + const MIint nPosColon = m_brkName.find(cColon); + if (nPosColon != (MIint)std::string::npos) + { + CMIUtilString::VecString_t vecFileAndLocation; + const MIuint nSplits = m_brkName.Split(cColon, vecFileAndLocation); + MIunused(nSplits); + if (vecFileAndLocation.size() != 2) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_LOCATION_FORMAT), m_cmdData.strMiCmd.c_str(), m_brkName.c_str())); + return MIstatus::failure; + } + fileName = vecFileAndLocation.at(0); + const CMIUtilString &rStrLineOrFn(vecFileAndLocation.at(1)); + if (rStrLineOrFn.empty()) + eBrkPtType = eBreakPoint_ByName; + else + { + MIint64 nValue = 0; + if (rStrLineOrFn.ExtractNumber(nValue)) + { + nFileLine = static_cast(nValue); + eBrkPtType = eBreakPoint_ByFileLine; + } + else + { + strFileFn = rStrLineOrFn; + eBrkPtType = eBreakPoint_ByFileFn; + } + } + } + + // Determine if break defined as an address + lldb::addr_t nAddress = 0; + if (eBrkPtType == eBreakPoint_NotDefineYet) + { + MIint64 nValue = 0; + if (m_brkName.ExtractNumber(nValue)) + { + nAddress = static_cast(nValue); + eBrkPtType = eBreakPoint_ByAddress; + } + } + + // Break defined as an function + if (eBrkPtType == eBreakPoint_NotDefineYet) + { + eBrkPtType = eBreakPoint_ByName; + } + + // Ask LLDB to create a breakpoint + bool bOk = MIstatus::success; + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBTarget &rTarget = rSessionInfo.m_lldbTarget; + switch (eBrkPtType) + { + case eBreakPoint_ByAddress: + m_brkPt = rTarget.BreakpointCreateByAddress(nAddress); + break; + case eBreakPoint_ByFileFn: + m_brkPt = rTarget.BreakpointCreateByName(strFileFn.c_str(), fileName.c_str()); + break; + case eBreakPoint_ByFileLine: + m_brkPt = rTarget.BreakpointCreateByLocation(fileName.c_str(), nFileLine); + break; + case eBreakPoint_ByName: + m_brkPt = rTarget.BreakpointCreateByName(m_brkName.c_str(), rTarget.GetExecutable().GetFilename()); + break; + case eBreakPoint_count: + case eBreakPoint_NotDefineYet: + case eBreakPoint_Invalid: + bOk = MIstatus::failure; + break; + } + + if (bOk) + { + m_brkPt.SetEnabled(m_bBrkPtEnabled); + m_brkPt.SetIgnoreCount(m_nBrkPtIgnoreCount); + if (m_bBrkPtCondition) + m_brkPt.SetCondition(m_brkPtCondition.c_str()); + if (m_bBrkPtThreadId) + m_brkPt.SetThreadID(m_nBrkPtThreadId); + if (!m_brkPt.IsValid()) + m_bBrkPtIsPending = pArgPendingBrkPt->GetFound(); + } + + // CODETAG_LLDB_BREAKPOINT_CREATION + // This is in the main thread + // Record break point information to be by LLDB event handler function + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; + sBrkPtInfo.m_id = m_brkPt.GetID(); + sBrkPtInfo.m_bDisp = m_bBrkPtIsTemp; + sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled; + sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp; + sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp; + sBrkPtInfo.m_strOrigLoc = m_brkName; + sBrkPtInfo.m_nIgnore = m_nBrkPtIgnoreCount; + sBrkPtInfo.m_bPending = m_bBrkPtIsPending; + sBrkPtInfo.m_bCondition = m_bBrkPtCondition; + sBrkPtInfo.m_strCondition = m_brkPtCondition; + sBrkPtInfo.m_bBrkPtThreadId = m_bBrkPtThreadId; + sBrkPtInfo.m_nBrkPtThreadId = m_nBrkPtThreadId; + bOk = bOk && rSessionInfo.RecordBrkPtInfo(m_brkPt.GetID(), sBrkPtInfo); + + if (!bOk) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_brkName.c_str())); + return MIstatus::failure; + } + + // CODETAG_LLDB_BRKPT_ID_MAX + if (m_brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), m_cmdData.strMiCmd.c_str(), rSessionInfo.m_nBrkPointCntMax, + m_brkName.c_str())); + return MIstatus::failure; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakInsert::Acknowledge( void ) +bool +CMICmdCmdBreakInsert::Acknowledge(void) { - // Get breakpoint information - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; - if( !rSessionInfo.GetBrkPtInfo( m_brkPt, sBrkPtInfo ) ) - { - return MIstatus::failure; - } - - // CODETAG_LLDB_BREAKPOINT_CREATION - // Add more breakpoint information or overwrite existing information - sBrkPtInfo.m_bDisp = m_bBrkPtIsTemp; - sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled; - sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp; - sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp; - sBrkPtInfo.m_nTimes = m_brkPt.GetNumLocations(); - sBrkPtInfo.m_strOrigLoc = m_brkName; - sBrkPtInfo.m_nIgnore = m_nBrkPtIgnoreCount; - sBrkPtInfo.m_bPending = m_bBrkPtIsPending; - sBrkPtInfo.m_bCondition = m_bBrkPtCondition; - sBrkPtInfo.m_strCondition = m_brkPtCondition; - sBrkPtInfo.m_bBrkPtThreadId = m_bBrkPtThreadId; - sBrkPtInfo.m_nBrkPtThreadId = m_nBrkPtThreadId; - - // MI print "^done,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",thread-groups=[\"%s\"],times=\"%d\",original-location=\"%s\"}" - CMICmnMIValueTuple miValueTuple; - if( !rSessionInfo.MIResponseFormBrkPtInfo( sBrkPtInfo, miValueTuple ) ) - { - return MIstatus::failure; - } - - const CMICmnMIValueResult miValueResultD( "bkpt", miValueTuple ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResultD ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + // Get breakpoint information + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; + if (!rSessionInfo.GetBrkPtInfo(m_brkPt, sBrkPtInfo)) + { + return MIstatus::failure; + } + + // CODETAG_LLDB_BREAKPOINT_CREATION + // Add more breakpoint information or overwrite existing information + sBrkPtInfo.m_bDisp = m_bBrkPtIsTemp; + sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled; + sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp; + sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp; + sBrkPtInfo.m_nTimes = m_brkPt.GetNumLocations(); + sBrkPtInfo.m_strOrigLoc = m_brkName; + sBrkPtInfo.m_nIgnore = m_nBrkPtIgnoreCount; + sBrkPtInfo.m_bPending = m_bBrkPtIsPending; + sBrkPtInfo.m_bCondition = m_bBrkPtCondition; + sBrkPtInfo.m_strCondition = m_brkPtCondition; + sBrkPtInfo.m_bBrkPtThreadId = m_bBrkPtThreadId; + sBrkPtInfo.m_nBrkPtThreadId = m_nBrkPtThreadId; + + // MI print + // "^done,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",thread-groups=[\"%s\"],times=\"%d\",original-location=\"%s\"}" + CMICmnMIValueTuple miValueTuple; + if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple)) + { + return MIstatus::failure; + } + + const CMICmnMIValueResult miValueResultD("bkpt", miValueTuple); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResultD); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdBreakInsert::CreateSelf( void ) +CMICmdBase * +CMICmdCmdBreakInsert::CreateSelf(void) { - return new CMICmdCmdBreakInsert(); + return new CMICmdCmdBreakInsert(); } //--------------------------------------------------------------------------------------- @@ -353,111 +370,117 @@ CMICmdBase * CMICmdCmdBreakInsert::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdBreakDelete constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdBreakDelete constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdBreakDelete::CMICmdCmdBreakDelete( void ) -: m_constStrArgNamedBrkPt( "breakpoint" ) -, m_constStrArgNamedThreadGrp( "thread-group" ) +CMICmdCmdBreakDelete::CMICmdCmdBreakDelete(void) + : m_constStrArgNamedBrkPt("breakpoint") + , m_constStrArgNamedThreadGrp("thread-group") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "break-delete"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdBreakDelete::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "break-delete"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdBreakDelete::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdBreakDelete destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdBreakDelete destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete( void ) +CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakDelete::ParseArgs( void ) +bool +CMICmdCmdBreakDelete::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add( + *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); + bOk = + bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakDelete::Execute( void ) +bool +CMICmdCmdBreakDelete::Execute(void) { - CMICMDBASE_GETOPTION( pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt ); - - // ATM we only handle one break point ID - MIuint64 nBrk = UINT64_MAX; - if( !pArgBrkPt->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nBrk ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str() ) ); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - const bool bBrkPt = rSessionInfo.m_lldbTarget.BreakpointDelete( static_cast< lldb::break_id_t >( nBrk ) ); - if( !bBrkPt ) - { - const CMIUtilString strBrkNum( CMIUtilString::Format( "%d", nBrk ) ); - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), strBrkNum.c_str() ) ); - return MIstatus::failure; - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt); + + // ATM we only handle one break point ID + MIuint64 nBrk = UINT64_MAX; + if (!pArgBrkPt->GetExpectedOption(nBrk)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + const bool bBrkPt = rSessionInfo.m_lldbTarget.BreakpointDelete(static_cast(nBrk)); + if (!bBrkPt) + { + const CMIUtilString strBrkNum(CMIUtilString::Format("%d", nBrk)); + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), strBrkNum.c_str())); + return MIstatus::failure; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakDelete::Acknowledge( void ) +bool +CMICmdCmdBreakDelete::Acknowledge(void) { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done ); - m_miResultRecord = miRecordResult; + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdBreakDelete::CreateSelf( void ) +CMICmdBase * +CMICmdCmdBreakDelete::CreateSelf(void) { - return new CMICmdCmdBreakDelete(); + return new CMICmdCmdBreakDelete(); } //--------------------------------------------------------------------------------------- @@ -465,133 +488,139 @@ CMICmdBase * CMICmdCmdBreakDelete::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdBreakDisable constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdBreakDisable constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdBreakDisable::CMICmdCmdBreakDisable( void ) -: m_constStrArgNamedThreadGrp( "thread-group" ) -, m_constStrArgNamedBrkPt( "breakpoint" ) -, m_bBrkPtDisabledOk( false ) -, m_nBrkPtId( 0 ) +CMICmdCmdBreakDisable::CMICmdCmdBreakDisable(void) + : m_constStrArgNamedThreadGrp("thread-group") + , m_constStrArgNamedBrkPt("breakpoint") + , m_bBrkPtDisabledOk(false) + , m_nBrkPtId(0) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "break-disable"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdBreakDisable::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "break-disable"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdBreakDisable::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdBreakDisable destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdBreakDisable destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable( void ) +CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakDisable::ParseArgs( void ) +bool +CMICmdCmdBreakDisable::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add( + *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); + bOk = + bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakDisable::Execute( void ) +bool +CMICmdCmdBreakDisable::Execute(void) { - CMICMDBASE_GETOPTION( pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt ); - - // ATM we only handle one break point ID - MIuint64 nBrk = UINT64_MAX; - if( !pArgBrkPt->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nBrk ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str() ) ); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID( static_cast< lldb::break_id_t >( nBrk ) ); - if( brkPt.IsValid() ) - { - m_bBrkPtDisabledOk = true; - brkPt.SetEnabled( false ); - m_nBrkPtId = nBrk; - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt); + + // ATM we only handle one break point ID + MIuint64 nBrk = UINT64_MAX; + if (!pArgBrkPt->GetExpectedOption(nBrk)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID(static_cast(nBrk)); + if (brkPt.IsValid()) + { + m_bBrkPtDisabledOk = true; + brkPt.SetEnabled(false); + m_nBrkPtId = nBrk; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakDisable::Acknowledge( void ) +bool +CMICmdCmdBreakDisable::Acknowledge(void) { - if( m_bBrkPtDisabledOk ) - { - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", m_nBrkPtId ) ); - const CMICmnMIValueResult miValueResult( "number", miValueConst ); - CMICmnMIValueTuple miValueTuple( miValueResult ); - const CMICmnMIValueConst miValueConst2( "n" ); - const CMICmnMIValueResult miValueResult2( "enabled", miValueConst2 ); - bool bOk = miValueTuple.Add( miValueResult2 ); - const CMICmnMIValueResult miValueResult3( "bkpt", miValueTuple ); - const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult3 ); - bOk = bOk && CMICmnStreamStdout::TextToStdout( miOutOfBandRecord.GetString() ); - - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done ); - m_miResultRecord = miRecordResult; - return bOk; - } - - const CMIUtilString strBrkPtId( CMIUtilString::Format( "%d", m_nBrkPtId ) ); - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), strBrkPtId.c_str() ) ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + if (m_bBrkPtDisabledOk) + { + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", m_nBrkPtId)); + const CMICmnMIValueResult miValueResult("number", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueConst miValueConst2("n"); + const CMICmnMIValueResult miValueResult2("enabled", miValueConst2); + bool bOk = miValueTuple.Add(miValueResult2); + const CMICmnMIValueResult miValueResult3("bkpt", miValueTuple); + const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult3); + bOk = bOk && CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString()); + + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; + return bOk; + } + + const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); + const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str())); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdBreakDisable::CreateSelf( void ) +CMICmdBase * +CMICmdCmdBreakDisable::CreateSelf(void) { - return new CMICmdCmdBreakDisable(); + return new CMICmdCmdBreakDisable(); } //--------------------------------------------------------------------------------------- @@ -599,133 +628,139 @@ CMICmdBase * CMICmdCmdBreakDisable::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdBreakEnable constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdBreakEnable constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdBreakEnable::CMICmdCmdBreakEnable( void ) -: m_constStrArgNamedThreadGrp( "thread-group" ) -, m_constStrArgNamedBrkPt( "breakpoint" ) -, m_bBrkPtEnabledOk( false ) -, m_nBrkPtId( 0 ) +CMICmdCmdBreakEnable::CMICmdCmdBreakEnable(void) + : m_constStrArgNamedThreadGrp("thread-group") + , m_constStrArgNamedBrkPt("breakpoint") + , m_bBrkPtEnabledOk(false) + , m_nBrkPtId(0) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "break-enable"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdBreakEnable::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "break-enable"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdBreakEnable::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdBreakEnable destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdBreakEnable destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable( void ) +CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakEnable::ParseArgs( void ) +bool +CMICmdCmdBreakEnable::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add( + *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); + bOk = + bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakEnable::Execute( void ) +bool +CMICmdCmdBreakEnable::Execute(void) { - CMICMDBASE_GETOPTION( pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt ); - - // ATM we only handle one break point ID - MIuint64 nBrk = UINT64_MAX; - if( !pArgBrkPt->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nBrk ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str() ) ); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID( static_cast< lldb::break_id_t >( nBrk ) ); - if( brkPt.IsValid() ) - { - m_bBrkPtEnabledOk = true; - brkPt.SetEnabled( false ); - m_nBrkPtId = nBrk; - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt); + + // ATM we only handle one break point ID + MIuint64 nBrk = UINT64_MAX; + if (!pArgBrkPt->GetExpectedOption(nBrk)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID(static_cast(nBrk)); + if (brkPt.IsValid()) + { + m_bBrkPtEnabledOk = true; + brkPt.SetEnabled(false); + m_nBrkPtId = nBrk; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakEnable::Acknowledge( void ) +bool +CMICmdCmdBreakEnable::Acknowledge(void) { - if( m_bBrkPtEnabledOk ) - { - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", m_nBrkPtId ) ); - const CMICmnMIValueResult miValueResult( "number", miValueConst ); - CMICmnMIValueTuple miValueTuple( miValueResult ); - const CMICmnMIValueConst miValueConst2( "y" ); - const CMICmnMIValueResult miValueResult2( "enabled", miValueConst2 ); - bool bOk = miValueTuple.Add( miValueResult2 ); - const CMICmnMIValueResult miValueResult3( "bkpt", miValueTuple ); - const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult3 ); - bOk = bOk && CMICmnStreamStdout::TextToStdout( miOutOfBandRecord.GetString() ); - - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done ); - m_miResultRecord = miRecordResult; - return bOk; - } - - const CMIUtilString strBrkPtId( CMIUtilString::Format( "%d", m_nBrkPtId ) ); - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), strBrkPtId.c_str() ) ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + if (m_bBrkPtEnabledOk) + { + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", m_nBrkPtId)); + const CMICmnMIValueResult miValueResult("number", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueConst miValueConst2("y"); + const CMICmnMIValueResult miValueResult2("enabled", miValueConst2); + bool bOk = miValueTuple.Add(miValueResult2); + const CMICmnMIValueResult miValueResult3("bkpt", miValueTuple); + const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult3); + bOk = bOk && CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString()); + + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; + return bOk; + } + + const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); + const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str())); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdBreakEnable::CreateSelf( void ) +CMICmdBase * +CMICmdCmdBreakEnable::CreateSelf(void) { - return new CMICmdCmdBreakEnable(); + return new CMICmdCmdBreakEnable(); } //--------------------------------------------------------------------------------------- @@ -733,124 +768,129 @@ CMICmdBase * CMICmdCmdBreakEnable::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdBreakAfter constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdBreakAfter constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdBreakAfter::CMICmdCmdBreakAfter( void ) -: m_constStrArgNamedThreadGrp( "thread-group" ) -, m_constStrArgNamedNumber( "number" ) -, m_constStrArgNamedCount( "count" ) -, m_nBrkPtId( 0 ) -, m_nBrkPtCount( 0 ) +CMICmdCmdBreakAfter::CMICmdCmdBreakAfter(void) + : m_constStrArgNamedThreadGrp("thread-group") + , m_constStrArgNamedNumber("number") + , m_constStrArgNamedCount("count") + , m_nBrkPtId(0) + , m_nBrkPtCount(0) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "break-after"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdBreakAfter::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "break-after"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdBreakAfter::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdBreakAfter destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdBreakAfter destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter( void ) +CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakAfter::ParseArgs( void ) +bool +CMICmdCmdBreakAfter::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNamedNumber, true, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNamedCount, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add( + *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNamedCount, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakAfter::Execute( void ) +bool +CMICmdCmdBreakAfter::Execute(void) { - CMICMDBASE_GETOPTION( pArgNumber, Number, m_constStrArgNamedNumber ); - CMICMDBASE_GETOPTION( pArgCount, Number, m_constStrArgNamedCount ); - - m_nBrkPtId = pArgNumber->GetValue(); - m_nBrkPtCount = pArgCount->GetValue(); - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID( static_cast< lldb::break_id_t >( m_nBrkPtId ) ); - if( brkPt.IsValid() ) - { - brkPt.SetIgnoreCount( m_nBrkPtCount ); - - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; - if( !rSessionInfo.RecordBrkPtInfoGet( m_nBrkPtId, sBrkPtInfo ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_nBrkPtId ) ); - return MIstatus::failure; - } - sBrkPtInfo.m_nIgnore = m_nBrkPtCount; - rSessionInfo.RecordBrkPtInfo( m_nBrkPtId, sBrkPtInfo ); - } - else - { - const CMIUtilString strBrkPtId( CMIUtilString::Format( "%d", m_nBrkPtId ) ); - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), strBrkPtId.c_str() ) ); - return MIstatus::failure; - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber); + CMICMDBASE_GETOPTION(pArgCount, Number, m_constStrArgNamedCount); + + m_nBrkPtId = pArgNumber->GetValue(); + m_nBrkPtCount = pArgCount->GetValue(); + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID(static_cast(m_nBrkPtId)); + if (brkPt.IsValid()) + { + brkPt.SetIgnoreCount(m_nBrkPtCount); + + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; + if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_nBrkPtId)); + return MIstatus::failure; + } + sBrkPtInfo.m_nIgnore = m_nBrkPtCount; + rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo); + } + else + { + const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), strBrkPtId.c_str())); + return MIstatus::failure; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakAfter::Acknowledge( void ) +bool +CMICmdCmdBreakAfter::Acknowledge(void) { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done ); - m_miResultRecord = miRecordResult; + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdBreakAfter::CreateSelf( void ) +CMICmdBase * +CMICmdCmdBreakAfter::CreateSelf(void) { - return new CMICmdCmdBreakAfter(); + return new CMICmdCmdBreakAfter(); } //--------------------------------------------------------------------------------------- @@ -858,169 +898,178 @@ CMICmdBase * CMICmdCmdBreakAfter::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdBreakCondition constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdBreakCondition constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdBreakCondition::CMICmdCmdBreakCondition( void ) -: m_constStrArgNamedThreadGrp( "thread-group" ) -, m_constStrArgNamedNumber( "number" ) -, m_constStrArgNamedExpr( "expr" ) -, m_constStrArgNamedExprNoQuotes( "expression not surround by quotes" ) // Not specified in MI spec, we need to handle expressions not surrounded by quotes -, m_nBrkPtId( 0 ) +CMICmdCmdBreakCondition::CMICmdCmdBreakCondition(void) + : m_constStrArgNamedThreadGrp("thread-group") + , m_constStrArgNamedNumber("number") + , m_constStrArgNamedExpr("expr") + , m_constStrArgNamedExprNoQuotes( + "expression not surround by quotes") // Not specified in MI spec, we need to handle expressions not surrounded by quotes + , m_nBrkPtId(0) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "break-condition"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdBreakCondition::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "break-condition"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdBreakCondition::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdBreakCondition destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdBreakCondition destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition( void ) +CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakCondition::ParseArgs( void ) +bool +CMICmdCmdBreakCondition::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNamedNumber, true, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedExpr, true, true, true, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgNamedExprNoQuotes, true, false, CMICmdArgValListBase::eArgValType_StringQuotedNumber ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add( + *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedExpr, true, true, true, true))); + bOk = bOk && + m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgNamedExprNoQuotes, true, false, + CMICmdArgValListBase::eArgValType_StringQuotedNumber))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakCondition::Execute( void ) +bool +CMICmdCmdBreakCondition::Execute(void) { - CMICMDBASE_GETOPTION( pArgNumber, Number, m_constStrArgNamedNumber ); - CMICMDBASE_GETOPTION( pArgExpr, String, m_constStrArgNamedExpr ); - - m_nBrkPtId = pArgNumber->GetValue(); - m_strBrkPtExpr = pArgExpr->GetValue(); - m_strBrkPtExpr += GetRestOfExpressionNotSurroundedInQuotes(); - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID( static_cast< lldb::break_id_t >( m_nBrkPtId ) ); - if( brkPt.IsValid() ) - { - brkPt.SetCondition( m_strBrkPtExpr.c_str() ); - - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; - if( !rSessionInfo.RecordBrkPtInfoGet( m_nBrkPtId, sBrkPtInfo ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_nBrkPtId ) ); - return MIstatus::failure; - } - sBrkPtInfo.m_strCondition = m_strBrkPtExpr; - rSessionInfo.RecordBrkPtInfo( m_nBrkPtId, sBrkPtInfo ); - } - else - { - const CMIUtilString strBrkPtId( CMIUtilString::Format( "%d", m_nBrkPtId ) ); - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), strBrkPtId.c_str() ) ); - return MIstatus::failure; - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber); + CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgNamedExpr); + + m_nBrkPtId = pArgNumber->GetValue(); + m_strBrkPtExpr = pArgExpr->GetValue(); + m_strBrkPtExpr += GetRestOfExpressionNotSurroundedInQuotes(); + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID(static_cast(m_nBrkPtId)); + if (brkPt.IsValid()) + { + brkPt.SetCondition(m_strBrkPtExpr.c_str()); + + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; + if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_nBrkPtId)); + return MIstatus::failure; + } + sBrkPtInfo.m_strCondition = m_strBrkPtExpr; + rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo); + } + else + { + const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), strBrkPtId.c_str())); + return MIstatus::failure; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdBreakCondition::Acknowledge( void ) +bool +CMICmdCmdBreakCondition::Acknowledge(void) { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done ); - m_miResultRecord = miRecordResult; + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdBreakCondition::CreateSelf( void ) +CMICmdBase * +CMICmdCmdBreakCondition::CreateSelf(void) { - return new CMICmdCmdBreakCondition(); + return new CMICmdCmdBreakCondition(); } //++ ------------------------------------------------------------------------------------ -// Details: A breakpoint expression can be passed to *this command as: -// a single string i.e. '2' -> ok. -// a quoted string i.e. "a > 100" -> ok -// a non quoted string i.e. 'a > 100' -> not ok -// CMICmdArgValString only extracts the first space seperated string, the "a". -// This function using the optional argument type CMICmdArgValListOfN collects -// the rest of the expression so that is may be added to the 'a' part to form a -// complete expression string i.e. "a > 100". -// If the expression value was guaranteed to be surrounded by quotes them this -// function would not be necessary. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Rest of the breakpoint expression. -// Throws: None. +// Details: A breakpoint expression can be passed to *this command as: +// a single string i.e. '2' -> ok. +// a quoted string i.e. "a > 100" -> ok +// a non quoted string i.e. 'a > 100' -> not ok +// CMICmdArgValString only extracts the first space seperated string, the "a". +// This function using the optional argument type CMICmdArgValListOfN collects +// the rest of the expression so that is may be added to the 'a' part to form a +// complete expression string i.e. "a > 100". +// If the expression value was guaranteed to be surrounded by quotes them this +// function would not be necessary. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Rest of the breakpoint expression. +// Throws: None. //-- -CMIUtilString CMICmdCmdBreakCondition::GetRestOfExpressionNotSurroundedInQuotes( void ) +CMIUtilString +CMICmdCmdBreakCondition::GetRestOfExpressionNotSurroundedInQuotes(void) { - CMIUtilString strExpression; - - CMICmdArgValListOfN * pArgExprNoQuotes = CMICmdBase::GetOption< CMICmdArgValListOfN >( m_constStrArgNamedExprNoQuotes ); - if( pArgExprNoQuotes != nullptr ) - { - CMIUtilString strExpression; - const CMICmdArgValListBase::VecArgObjPtr_t & rVecExprParts( pArgExprNoQuotes->GetExpectedOptions() ); - if( !rVecExprParts.empty() ) - { - CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecExprParts.begin(); - while( it != rVecExprParts.end() ) - { - const CMICmdArgValString * pPartExpr = static_cast< CMICmdArgValString * >( *it ); - const CMIUtilString & rPartExpr = pPartExpr->GetValue(); - strExpression += " "; - strExpression += rPartExpr; - - // Next - ++it; - } - strExpression = strExpression.Trim(); - } - } - - return strExpression; + CMIUtilString strExpression; + + CMICmdArgValListOfN *pArgExprNoQuotes = CMICmdBase::GetOption(m_constStrArgNamedExprNoQuotes); + if (pArgExprNoQuotes != nullptr) + { + CMIUtilString strExpression; + const CMICmdArgValListBase::VecArgObjPtr_t &rVecExprParts(pArgExprNoQuotes->GetExpectedOptions()); + if (!rVecExprParts.empty()) + { + CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecExprParts.begin(); + while (it != rVecExprParts.end()) + { + const CMICmdArgValString *pPartExpr = static_cast(*it); + const CMIUtilString &rPartExpr = pPartExpr->GetValue(); + strExpression += " "; + strExpression += rPartExpr; + + // Next + ++it; + } + strExpression = strExpression.Trim(); + } + } + + return strExpression; } diff --git a/tools/lldb-mi/MICmdCmdBreak.h b/tools/lldb-mi/MICmdCmdBreak.h index e5283d609905..c9540b0521eb 100644 --- a/tools/lldb-mi/MICmdCmdBreak.h +++ b/tools/lldb-mi/MICmdCmdBreak.h @@ -8,29 +8,29 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdBreak.h +// File: MICmdCmdBreak.h // -// Overview: CMICmdCmdBreakInsert interface. -// CMICmdCmdBreakDelete interface. -// CMICmdCmdBreakDisable interface. -// CMICmdCmdBreakEnable interface. -// CMICmdCmdBreakAfter interface. -// CMICmdCmdBreakCondition interface. +// Overview: CMICmdCmdBreakInsert interface. +// CMICmdCmdBreakDelete interface. +// CMICmdCmdBreakDisable interface. +// CMICmdCmdBreakEnable interface. +// CMICmdCmdBreakAfter interface. +// CMICmdCmdBreakCondition interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -42,251 +42,251 @@ #include "MICmdBase.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "break-insert". -// This command does not follow the MI documentation exactly. -// Gotchas: None. -// Authors: Illya Rudkin 11/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "break-insert". +// This command does not follow the MI documentation exactly. +// Gotchas: None. +// Authors: Illya Rudkin 11/03/2014. +// Changes: None. //-- class CMICmdCmdBreakInsert : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdBreakInsert( void ); + // Methods: + public: + /* ctor */ CMICmdCmdBreakInsert(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdBreakInsert( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdBreakInsert(void); -// Enumerations: -private: - //++ =================================================================== - // Details: The type of break point give in the MI command text. - //-- - enum BreakPoint_e - { - eBreakPoint_Invalid = 0, - eBreakPoint_ByFileLine, - eBreakPoint_ByFileFn, - eBreakPoint_ByName, - eBreakPoint_ByAddress, - eBreakPoint_count, - eBreakPoint_NotDefineYet - }; + // Enumerations: + private: + //++ =================================================================== + // Details: The type of break point give in the MI command text. + //-- + enum BreakPoint_e + { + eBreakPoint_Invalid = 0, + eBreakPoint_ByFileLine, + eBreakPoint_ByFileFn, + eBreakPoint_ByName, + eBreakPoint_ByAddress, + eBreakPoint_count, + eBreakPoint_NotDefineYet + }; -// Attributes: -private: - bool m_bBrkPtIsTemp; - bool m_bHaveArgOptionThreadGrp; - CMIUtilString m_brkName; - CMIUtilString m_strArgOptionThreadGrp; - lldb::SBBreakpoint m_brkPt; - bool m_bBrkPtIsPending; - MIuint m_nBrkPtIgnoreCount; - bool m_bBrkPtEnabled; - bool m_bBrkPtCondition; - CMIUtilString m_brkPtCondition; - bool m_bBrkPtThreadId; - MIuint m_nBrkPtThreadId; - const CMIUtilString m_constStrArgNamedTempBrkPt; - const CMIUtilString m_constStrArgNamedHWBrkPt; // Not handled by *this command - const CMIUtilString m_constStrArgNamedPendinfBrkPt; - const CMIUtilString m_constStrArgNamedDisableBrkPt; - const CMIUtilString m_constStrArgNamedTracePt; // Not handled by *this command - const CMIUtilString m_constStrArgNamedConditionalBrkPt; - const CMIUtilString m_constStrArgNamedInoreCnt; - const CMIUtilString m_constStrArgNamedRestrictBrkPtToThreadId; - const CMIUtilString m_constStrArgNamedLocation; - const CMIUtilString m_constStrArgNamedThreadGroup; // Not specified in MI spec but Eclipse gives this option sometimes + // Attributes: + private: + bool m_bBrkPtIsTemp; + bool m_bHaveArgOptionThreadGrp; + CMIUtilString m_brkName; + CMIUtilString m_strArgOptionThreadGrp; + lldb::SBBreakpoint m_brkPt; + bool m_bBrkPtIsPending; + MIuint m_nBrkPtIgnoreCount; + bool m_bBrkPtEnabled; + bool m_bBrkPtCondition; + CMIUtilString m_brkPtCondition; + bool m_bBrkPtThreadId; + MIuint m_nBrkPtThreadId; + const CMIUtilString m_constStrArgNamedTempBrkPt; + const CMIUtilString m_constStrArgNamedHWBrkPt; // Not handled by *this command + const CMIUtilString m_constStrArgNamedPendinfBrkPt; + const CMIUtilString m_constStrArgNamedDisableBrkPt; + const CMIUtilString m_constStrArgNamedTracePt; // Not handled by *this command + const CMIUtilString m_constStrArgNamedConditionalBrkPt; + const CMIUtilString m_constStrArgNamedInoreCnt; + const CMIUtilString m_constStrArgNamedRestrictBrkPtToThreadId; + const CMIUtilString m_constStrArgNamedLocation; + const CMIUtilString m_constStrArgNamedThreadGroup; // Not specified in MI spec but Eclipse gives this option sometimes }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "break-delete". -// Gotchas: None. -// Authors: Illya Rudkin 11/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "break-delete". +// Gotchas: None. +// Authors: Illya Rudkin 11/03/2014. +// Changes: None. //-- class CMICmdCmdBreakDelete : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdBreakDelete( void ); + // Methods: + public: + /* ctor */ CMICmdCmdBreakDelete(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdBreakDelete( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdBreakDelete(void); -// Attributes: -private: - const CMIUtilString m_constStrArgNamedBrkPt; - const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option + // Attributes: + private: + const CMIUtilString m_constStrArgNamedBrkPt; + const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "break-disable". -// Gotchas: None. -// Authors: Illya Rudkin 19/05/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "break-disable". +// Gotchas: None. +// Authors: Illya Rudkin 19/05/2014. +// Changes: None. //-- class CMICmdCmdBreakDisable : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdBreakDisable( void ); + // Methods: + public: + /* ctor */ CMICmdCmdBreakDisable(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdBreakDisable( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdBreakDisable(void); -// Attributes: -private: - const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgNamedBrkPt; - bool m_bBrkPtDisabledOk; - MIuint m_nBrkPtId; + // Attributes: + private: + const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgNamedBrkPt; + bool m_bBrkPtDisabledOk; + MIuint m_nBrkPtId; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "break-enable". -// Gotchas: None. -// Authors: Illya Rudkin 19/05/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "break-enable". +// Gotchas: None. +// Authors: Illya Rudkin 19/05/2014. +// Changes: None. //-- class CMICmdCmdBreakEnable : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdBreakEnable( void ); + // Methods: + public: + /* ctor */ CMICmdCmdBreakEnable(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdBreakEnable( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdBreakEnable(void); -// Attributes: -private: - const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgNamedBrkPt; - bool m_bBrkPtEnabledOk; - MIuint m_nBrkPtId; + // Attributes: + private: + const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgNamedBrkPt; + bool m_bBrkPtEnabledOk; + MIuint m_nBrkPtId; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "break-after". -// Gotchas: None. -// Authors: Illya Rudkin 29/05/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "break-after". +// Gotchas: None. +// Authors: Illya Rudkin 29/05/2014. +// Changes: None. //-- class CMICmdCmdBreakAfter : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdBreakAfter( void ); + // Methods: + public: + /* ctor */ CMICmdCmdBreakAfter(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdBreakAfter( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdBreakAfter(void); -// Attributes: -private: - const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgNamedNumber; - const CMIUtilString m_constStrArgNamedCount; - MIuint m_nBrkPtId; - MIuint m_nBrkPtCount; + // Attributes: + private: + const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgNamedNumber; + const CMIUtilString m_constStrArgNamedCount; + MIuint m_nBrkPtId; + MIuint m_nBrkPtCount; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "break-condition". -// Gotchas: None. -// Authors: Illya Rudkin 29/05/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "break-condition". +// Gotchas: None. +// Authors: Illya Rudkin 29/05/2014. +// Changes: None. //-- class CMICmdCmdBreakCondition : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdBreakCondition( void ); + // Methods: + public: + /* ctor */ CMICmdCmdBreakCondition(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdBreakCondition( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdBreakCondition(void); -// Methods: -private: - CMIUtilString GetRestOfExpressionNotSurroundedInQuotes( void ); + // Methods: + private: + CMIUtilString GetRestOfExpressionNotSurroundedInQuotes(void); -// Attributes: -private: - const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgNamedNumber; - const CMIUtilString m_constStrArgNamedExpr; - const CMIUtilString m_constStrArgNamedExprNoQuotes; // Not specified in MI spec, we need to handle expressions not surrounded by quotes - MIuint m_nBrkPtId; - CMIUtilString m_strBrkPtExpr; + // Attributes: + private: + const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgNamedNumber; + const CMIUtilString m_constStrArgNamedExpr; + const CMIUtilString m_constStrArgNamedExprNoQuotes; // Not specified in MI spec, we need to handle expressions not surrounded by quotes + MIuint m_nBrkPtId; + CMIUtilString m_strBrkPtExpr; }; diff --git a/tools/lldb-mi/MICmdCmdData.cpp b/tools/lldb-mi/MICmdCmdData.cpp index 69012ef042c4..e1abe83b9165 100644 --- a/tools/lldb-mi/MICmdCmdData.cpp +++ b/tools/lldb-mi/MICmdCmdData.cpp @@ -8,23 +8,23 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdData.cpp +// File: MICmdCmdData.cpp // -// Overview: CMICmdCmdDataEvaluateExpression implementation. -// CMICmdCmdDataDisassemble implementation. -// CMICmdCmdDataReadMemoryBytes implementation. -// CMICmdCmdDataReadMemory implementation. -// CMICmdCmdDataListRegisterNames implementation. -// CMICmdCmdDataListRegisterValues implementation. -// CMICmdCmdDataListRegisterChanged implementation. -// CMICmdCmdDataWriteMemoryBytes implementation. -// CMICmdCmdDataWriteMemory implementation. +// Overview: CMICmdCmdDataEvaluateExpression implementation. +// CMICmdCmdDataDisassemble implementation. +// CMICmdCmdDataReadMemoryBytes implementation. +// CMICmdCmdDataReadMemory implementation. +// CMICmdCmdDataListRegisterNames implementation. +// CMICmdCmdDataListRegisterValues implementation. +// CMICmdCmdDataListRegisterChanged implementation. +// CMICmdCmdDataWriteMemoryBytes implementation. +// CMICmdCmdDataWriteMemory implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third Party Headers: @@ -51,235 +51,245 @@ #include "MICmnLLDBUtilSBValue.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataEvaluateExpression constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataEvaluateExpression constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataEvaluateExpression::CMICmdCmdDataEvaluateExpression( void ) -: m_bExpressionValid( true ) -, m_bEvaluatedExpression( true ) -, m_strValue( "??" ) -, m_bCompositeVarType( false ) -, m_bFoundInvalidChar( false ) -, m_cExpressionInvalidChar( 0x00 ) -, m_constStrArgThread( "thread" ) -, m_constStrArgFrame( "frame" ) -, m_constStrArgExpr( "expr" ) +CMICmdCmdDataEvaluateExpression::CMICmdCmdDataEvaluateExpression(void) + : m_bExpressionValid(true) + , m_bEvaluatedExpression(true) + , m_strValue("??") + , m_bCompositeVarType(false) + , m_bFoundInvalidChar(false) + , m_cExpressionInvalidChar(0x00) + , m_constStrArgThread("thread") + , m_constStrArgFrame("frame") + , m_constStrArgExpr("expr") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-evaluate-expression"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataEvaluateExpression::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-evaluate-expression"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataEvaluateExpression::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataEvaluateExpression destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataEvaluateExpression destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression( void ) +CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataEvaluateExpression::ParseArgs( void ) +bool +CMICmdCmdDataEvaluateExpression::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgFrame, false, false, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgExpr, true, true, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgFrame, false, false, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgExpr, true, true, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataEvaluateExpression::Execute( void ) +bool +CMICmdCmdDataEvaluateExpression::Execute(void) { - CMICMDBASE_GETOPTION( pArgExpr, String, m_constStrArgExpr ); - - const CMIUtilString & rExpression( pArgExpr->GetValue() ); - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = rProcess.GetSelectedThread(); - m_bExpressionValid = (thread.GetNumFrames() > 0); - if( !m_bExpressionValid ) - return MIstatus::success; - - lldb::SBFrame frame = thread.GetSelectedFrame(); - lldb::SBValue value = frame.EvaluateExpression( rExpression.c_str() ); - if( !value.IsValid() ) - value = frame.FindVariable( rExpression.c_str() ); - if( !value.IsValid() ) - { - m_bEvaluatedExpression = false; - return MIstatus::success; - } - const CMICmnLLDBUtilSBValue utilValue( value ); - if( !utilValue.HasName() ) - { - if( HaveInvalidCharacterInExpression( rExpression, m_cExpressionInvalidChar ) ) - { - m_bFoundInvalidChar = true; - return MIstatus::success; - } - - m_strValue = rExpression; - return MIstatus::success; - } - if( rExpression.IsQuoted() ) - { - m_strValue = rExpression.Trim( '\"' ); - return MIstatus::success; - } - - MIuint64 nNumber = 0; - if( CMICmnLLDBProxySBValue::GetValueAsUnsigned( value, nNumber ) == MIstatus::success ) - { - const lldb::ValueType eValueType = value.GetValueType(); MIunused( eValueType ); - m_strValue = utilValue.GetValue(); - CMIUtilString strCString; - if( CMICmnLLDBProxySBValue::GetCString( value, strCString ) ) - { - m_strValue += CMIUtilString::Format( " '%s'", strCString.c_str() ); - } - return MIstatus::success; - } - - // Composite type i.e. struct - m_bCompositeVarType = true; - const MIuint nChild = value.GetNumChildren(); - for( MIuint i = 0; i < nChild; i++ ) - { - lldb::SBValue member = value.GetChildAtIndex( i ); - const bool bValid = member.IsValid(); - CMIUtilString strType( MIRSRC( IDS_WORD_UNKNOWNTYPE_BRKTS ) ); - if( bValid ) - { - const CMIUtilString strValue( CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted( member, CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural ) ); - const char * pTypeName = member.GetName(); - if( pTypeName != nullptr ) - strType = pTypeName; - - // MI print "{variable = 1, variable2 = 3, variable3 = 5}" - const bool bNoQuotes = true; - const CMICmnMIValueConst miValueConst( strValue, bNoQuotes ); - const bool bUseSpaces = true; - const CMICmnMIValueResult miValueResult( strType, miValueConst, bUseSpaces ); - m_miValueTuple.Add( miValueResult, bUseSpaces ); - } - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgExpr); + + const CMIUtilString &rExpression(pArgExpr->GetValue()); + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + lldb::SBThread thread = rProcess.GetSelectedThread(); + m_bExpressionValid = (thread.GetNumFrames() > 0); + if (!m_bExpressionValid) + return MIstatus::success; + + lldb::SBFrame frame = thread.GetSelectedFrame(); + lldb::SBValue value = frame.EvaluateExpression(rExpression.c_str()); + if (!value.IsValid()) + value = frame.FindVariable(rExpression.c_str()); + if (!value.IsValid()) + { + m_bEvaluatedExpression = false; + return MIstatus::success; + } + const CMICmnLLDBUtilSBValue utilValue(value); + if (!utilValue.HasName()) + { + if (HaveInvalidCharacterInExpression(rExpression, m_cExpressionInvalidChar)) + { + m_bFoundInvalidChar = true; + return MIstatus::success; + } + + m_strValue = rExpression; + return MIstatus::success; + } + if (rExpression.IsQuoted()) + { + m_strValue = rExpression.Trim('\"'); + return MIstatus::success; + } + + MIuint64 nNumber = 0; + if (CMICmnLLDBProxySBValue::GetValueAsUnsigned(value, nNumber) == MIstatus::success) + { + const lldb::ValueType eValueType = value.GetValueType(); + MIunused(eValueType); + m_strValue = utilValue.GetValue(); + CMIUtilString strCString; + if (CMICmnLLDBProxySBValue::GetCString(value, strCString)) + { + m_strValue += CMIUtilString::Format(" '%s'", strCString.c_str()); + } + return MIstatus::success; + } + + // Composite type i.e. struct + m_bCompositeVarType = true; + const MIuint nChild = value.GetNumChildren(); + for (MIuint i = 0; i < nChild; i++) + { + lldb::SBValue member = value.GetChildAtIndex(i); + const bool bValid = member.IsValid(); + CMIUtilString strType(MIRSRC(IDS_WORD_UNKNOWNTYPE_BRKTS)); + if (bValid) + { + const CMIUtilString strValue( + CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(member, CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural)); + const char *pTypeName = member.GetName(); + if (pTypeName != nullptr) + strType = pTypeName; + + // MI print "{variable = 1, variable2 = 3, variable3 = 5}" + const bool bNoQuotes = true; + const CMICmnMIValueConst miValueConst(strValue, bNoQuotes); + const bool bUseSpaces = true; + const CMICmnMIValueResult miValueResult(strType, miValueConst, bUseSpaces); + m_miValueTuple.Add(miValueResult, bUseSpaces); + } + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataEvaluateExpression::Acknowledge( void ) +bool +CMICmdCmdDataEvaluateExpression::Acknowledge(void) { - if( m_bExpressionValid ) - { - if( m_bEvaluatedExpression ) - { - if( m_bCompositeVarType ) - { - const CMICmnMIValueConst miValueConst( m_miValueTuple.GetString() ); - const CMICmnMIValueResult miValueResult( "value", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - if( m_bFoundInvalidChar ) - { - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "Invalid character '%c' in expression", m_cExpressionInvalidChar ) ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - const CMICmnMIValueConst miValueConst( m_strValue ); - const CMICmnMIValueResult miValueResult( "value", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - const CMICmnMIValueConst miValueConst( "Could not evaluate expression" ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - const CMICmnMIValueConst miValueConst( "Invalid expression" ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + if (m_bExpressionValid) + { + if (m_bEvaluatedExpression) + { + if (m_bCompositeVarType) + { + const CMICmnMIValueConst miValueConst(m_miValueTuple.GetString()); + const CMICmnMIValueResult miValueResult("value", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + if (m_bFoundInvalidChar) + { + const CMICmnMIValueConst miValueConst( + CMIUtilString::Format("Invalid character '%c' in expression", m_cExpressionInvalidChar)); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + const CMICmnMIValueConst miValueConst(m_strValue); + const CMICmnMIValueResult miValueResult("value", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + const CMICmnMIValueConst miValueConst("Could not evaluate expression"); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + const CMICmnMIValueConst miValueConst("Invalid expression"); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdDataEvaluateExpression::CreateSelf( void ) +CMICmdBase * +CMICmdCmdDataEvaluateExpression::CreateSelf(void) { - return new CMICmdCmdDataEvaluateExpression(); + return new CMICmdCmdDataEvaluateExpression(); } //++ ------------------------------------------------------------------------------------ -// Details: Examine the expression string to see if it contains invalid characters. -// Type: Method. -// Args: vrExpr - (R) Expression string given to *this command. -// vrwInvalidChar - (W) True = Invalid character found, false = nothing found. -// Return: bool - True = Invalid character found, false = nothing found. -// Throws: None. +// Details: Examine the expression string to see if it contains invalid characters. +// Type: Method. +// Args: vrExpr - (R) Expression string given to *this command. +// vrwInvalidChar - (W) True = Invalid character found, false = nothing found. +// Return: bool - True = Invalid character found, false = nothing found. +// Throws: None. //-- -bool CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression( const CMIUtilString & vrExpr, MIchar & vrwInvalidChar ) +bool +CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression(const CMIUtilString &vrExpr, MIchar &vrwInvalidChar) { - bool bFoundInvalidCharInExpression = false; - vrwInvalidChar = 0x00; - - if( vrExpr.at( 0 ) == '\\' ) - { - // Example: Mouse hover over "%5d" expression has \"%5d\" in it - bFoundInvalidCharInExpression = true; - vrwInvalidChar = '\\'; - } - - return bFoundInvalidCharInExpression; + bool bFoundInvalidCharInExpression = false; + vrwInvalidChar = 0x00; + + if (vrExpr.at(0) == '\\') + { + // Example: Mouse hover over "%5d" expression has \"%5d\" in it + bFoundInvalidCharInExpression = true; + vrwInvalidChar = '\\'; + } + + return bFoundInvalidCharInExpression; } //--------------------------------------------------------------------------------------- @@ -287,198 +297,211 @@ bool CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression( const CM //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataDisassemble constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataDisassemble constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataDisassemble::CMICmdCmdDataDisassemble( void ) -: m_constStrArgThread( "thread" ) -, m_constStrArgAddrStart( "s" ) -, m_constStrArgAddrEnd( "e" ) -, m_constStrArgConsume( "--" ) -, m_constStrArgMode( "mode" ) -, m_miValueList( true ) +CMICmdCmdDataDisassemble::CMICmdCmdDataDisassemble(void) + : m_constStrArgThread("thread") + , m_constStrArgAddrStart("s") + , m_constStrArgAddrEnd("e") + , m_constStrArgConsume("--") + , m_constStrArgMode("mode") + , m_miValueList(true) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-disassemble"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataDisassemble::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-disassemble"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataDisassemble::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataDisassemble destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataDisassemble destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble( void ) +CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataDisassemble::ParseArgs( void ) +bool +CMICmdCmdDataDisassemble::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgAddrStart, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgAddrEnd, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValConsume( m_constStrArgConsume, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgMode, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && + m_setCmdArgs.Add( + *(new CMICmdArgValOptionShort(m_constStrArgAddrStart, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1))); + bOk = bOk && + m_setCmdArgs.Add( + *(new CMICmdArgValOptionShort(m_constStrArgAddrEnd, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValConsume(m_constStrArgConsume, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgMode, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataDisassemble::Execute( void ) +bool +CMICmdCmdDataDisassemble::Execute(void) { - CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread ); - CMICMDBASE_GETOPTION( pArgAddrStart, OptionShort, m_constStrArgAddrStart ); - CMICMDBASE_GETOPTION( pArgAddrEnd, OptionShort, m_constStrArgAddrEnd ); - CMICMDBASE_GETOPTION( pArgMode, Number, m_constStrArgMode ); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_THREAD_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) ); - return MIstatus::failure; - } - CMIUtilString strAddrStart; - if( !pArgAddrStart->GetExpectedOption< CMICmdArgValString, CMIUtilString >( strAddrStart ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_DISASM_ADDR_START_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrStart.c_str() ) ); - return MIstatus::failure; - } - MIint64 nAddrStart = 0; - if( !strAddrStart.ExtractNumber( nAddrStart ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_DISASM_ADDR_START_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrStart.c_str() ) ); - return MIstatus::failure; - } - - CMIUtilString strAddrEnd; - if( !pArgAddrEnd->GetExpectedOption< CMICmdArgValString, CMIUtilString >( strAddrEnd ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_DISASM_ADDR_END_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str() ) ); - return MIstatus::failure; - } - MIint64 nAddrEnd = 0; - if( !strAddrEnd.ExtractNumber( nAddrEnd ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_DISASM_ADDR_END_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str() ) ); - return MIstatus::failure; - } - const MIuint nDisasmMode = pArgMode->GetValue(); - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBTarget & rTarget = rSessionInfo.m_lldbTarget; - lldb::addr_t lldbStartAddr = static_cast< lldb::addr_t >( nAddrStart ); - lldb::SBInstructionList instructions = rTarget.ReadInstructions( lldb::SBAddress( lldbStartAddr, rTarget ), nAddrEnd - nAddrStart ); - const MIuint nInstructions = instructions.GetSize(); - for( size_t i = 0; i < nInstructions; i++ ) - { - const MIchar * pUnknown = "??"; - lldb::SBInstruction instrt = instructions.GetInstructionAtIndex( i ); - const MIchar * pStrMnemonic = instrt.GetMnemonic( rTarget ); - pStrMnemonic = (pStrMnemonic != nullptr) ? pStrMnemonic : pUnknown; - lldb::SBAddress address = instrt.GetAddress(); - lldb::addr_t addr = address.GetLoadAddress( rTarget ); - const MIchar * pFnName = address.GetFunction().GetName(); - pFnName = (pFnName != nullptr) ? pFnName : pUnknown; - lldb::addr_t addrOffSet = address.GetOffset(); - const MIchar * pStrOperands = instrt.GetOperands( rTarget ); - pStrOperands = (pStrOperands != nullptr) ? pStrOperands : pUnknown; - - // MI "{address=\"0x%08llx\",func-name=\"%s\",offset=\"%lld\",inst=\"%s %s\"}" - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "0x%08llx", addr ) ); - const CMICmnMIValueResult miValueResult( "address", miValueConst ); - CMICmnMIValueTuple miValueTuple( miValueResult ); - const CMICmnMIValueConst miValueConst2( pFnName ); - const CMICmnMIValueResult miValueResult2( "func-name", miValueConst2 ); - miValueTuple.Add( miValueResult2 ); - const CMICmnMIValueConst miValueConst3( CMIUtilString::Format( "0x%lld", addrOffSet ) ); - const CMICmnMIValueResult miValueResult3( "offset", miValueConst3 ); - miValueTuple.Add( miValueResult3 ); - const CMICmnMIValueConst miValueConst4( CMIUtilString::Format( "%s %s", pStrMnemonic, pStrOperands ) ); - const CMICmnMIValueResult miValueResult4( "inst", miValueConst4 ); - miValueTuple.Add( miValueResult4 ); - - if( nDisasmMode == 1 ) - { - lldb::SBLineEntry lineEntry = address.GetLineEntry(); - const MIuint nLine = lineEntry.GetLine(); - const MIchar * pFileName = lineEntry.GetFileSpec().GetFilename(); - pFileName = (pFileName != nullptr) ? pFileName : pUnknown; - - // MI "src_and_asm_line={line=\"%u\",file=\"%s\",line_asm_insn=[ ]}" - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "0x%u", nLine ) ); - const CMICmnMIValueResult miValueResult( "line", miValueConst ); - CMICmnMIValueTuple miValueTuple2( miValueResult ); - const CMICmnMIValueConst miValueConst2( pFileName ); - const CMICmnMIValueResult miValueResult2( "file", miValueConst2 ); - miValueTuple2.Add( miValueResult2 ); - const CMICmnMIValueList miValueList( miValueTuple ); - const CMICmnMIValueResult miValueResult3( "line_asm_insn", miValueList ); - miValueTuple2.Add( miValueResult3 ); - const CMICmnMIValueResult miValueResult4( "src_and_asm_line", miValueTuple2 ); - m_miValueList.Add( miValueResult4 ); - } - else - { - m_miValueList.Add( miValueTuple ); - } - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + CMICMDBASE_GETOPTION(pArgAddrStart, OptionShort, m_constStrArgAddrStart); + CMICMDBASE_GETOPTION(pArgAddrEnd, OptionShort, m_constStrArgAddrEnd); + CMICMDBASE_GETOPTION(pArgMode, Number, m_constStrArgMode); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (!pArgThread->GetExpectedOption(nThreadId)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); + return MIstatus::failure; + } + CMIUtilString strAddrStart; + if (!pArgAddrStart->GetExpectedOption(strAddrStart)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID), m_cmdData.strMiCmd.c_str(), + m_constStrArgAddrStart.c_str())); + return MIstatus::failure; + } + MIint64 nAddrStart = 0; + if (!strAddrStart.ExtractNumber(nAddrStart)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID), m_cmdData.strMiCmd.c_str(), + m_constStrArgAddrStart.c_str())); + return MIstatus::failure; + } + + CMIUtilString strAddrEnd; + if (!pArgAddrEnd->GetExpectedOption(strAddrEnd)) + { + SetError( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str())); + return MIstatus::failure; + } + MIint64 nAddrEnd = 0; + if (!strAddrEnd.ExtractNumber(nAddrEnd)) + { + SetError( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str())); + return MIstatus::failure; + } + const MIuint nDisasmMode = pArgMode->GetValue(); + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBTarget &rTarget = rSessionInfo.m_lldbTarget; + lldb::addr_t lldbStartAddr = static_cast(nAddrStart); + lldb::SBInstructionList instructions = rTarget.ReadInstructions(lldb::SBAddress(lldbStartAddr, rTarget), nAddrEnd - nAddrStart); + const MIuint nInstructions = instructions.GetSize(); + for (size_t i = 0; i < nInstructions; i++) + { + const MIchar *pUnknown = "??"; + lldb::SBInstruction instrt = instructions.GetInstructionAtIndex(i); + const MIchar *pStrMnemonic = instrt.GetMnemonic(rTarget); + pStrMnemonic = (pStrMnemonic != nullptr) ? pStrMnemonic : pUnknown; + lldb::SBAddress address = instrt.GetAddress(); + lldb::addr_t addr = address.GetLoadAddress(rTarget); + const MIchar *pFnName = address.GetFunction().GetName(); + pFnName = (pFnName != nullptr) ? pFnName : pUnknown; + lldb::addr_t addrOffSet = address.GetOffset(); + const MIchar *pStrOperands = instrt.GetOperands(rTarget); + pStrOperands = (pStrOperands != nullptr) ? pStrOperands : pUnknown; + + // MI "{address=\"0x%08llx\",func-name=\"%s\",offset=\"%lld\",inst=\"%s %s\"}" + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%08llx", addr)); + const CMICmnMIValueResult miValueResult("address", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueConst miValueConst2(pFnName); + const CMICmnMIValueResult miValueResult2("func-name", miValueConst2); + miValueTuple.Add(miValueResult2); + const CMICmnMIValueConst miValueConst3(CMIUtilString::Format("0x%lld", addrOffSet)); + const CMICmnMIValueResult miValueResult3("offset", miValueConst3); + miValueTuple.Add(miValueResult3); + const CMICmnMIValueConst miValueConst4(CMIUtilString::Format("%s %s", pStrMnemonic, pStrOperands)); + const CMICmnMIValueResult miValueResult4("inst", miValueConst4); + miValueTuple.Add(miValueResult4); + + if (nDisasmMode == 1) + { + lldb::SBLineEntry lineEntry = address.GetLineEntry(); + const MIuint nLine = lineEntry.GetLine(); + const MIchar *pFileName = lineEntry.GetFileSpec().GetFilename(); + pFileName = (pFileName != nullptr) ? pFileName : pUnknown; + + // MI "src_and_asm_line={line=\"%u\",file=\"%s\",line_asm_insn=[ ]}" + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%u", nLine)); + const CMICmnMIValueResult miValueResult("line", miValueConst); + CMICmnMIValueTuple miValueTuple2(miValueResult); + const CMICmnMIValueConst miValueConst2(pFileName); + const CMICmnMIValueResult miValueResult2("file", miValueConst2); + miValueTuple2.Add(miValueResult2); + const CMICmnMIValueList miValueList(miValueTuple); + const CMICmnMIValueResult miValueResult3("line_asm_insn", miValueList); + miValueTuple2.Add(miValueResult3); + const CMICmnMIValueResult miValueResult4("src_and_asm_line", miValueTuple2); + m_miValueList.Add(miValueResult4); + } + else + { + m_miValueList.Add(miValueTuple); + } + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataDisassemble::Acknowledge( void ) +bool +CMICmdCmdDataDisassemble::Acknowledge(void) { - const CMICmnMIValueResult miValueResult( "asm_insns", m_miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + const CMICmnMIValueResult miValueResult("asm_insns", m_miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdDataDisassemble::CreateSelf( void ) +CMICmdBase * +CMICmdCmdDataDisassemble::CreateSelf(void) { - return new CMICmdCmdDataDisassemble(); + return new CMICmdCmdDataDisassemble(); } //--------------------------------------------------------------------------------------- @@ -486,165 +509,175 @@ CMICmdBase * CMICmdCmdDataDisassemble::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataReadMemoryBytes constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataReadMemoryBytes constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataReadMemoryBytes::CMICmdCmdDataReadMemoryBytes( void ) -: m_constStrArgThread( "thread" ) -, m_constStrArgByteOffset( "o" ) -, m_constStrArgAddrStart( "address" ) -, m_constStrArgNumBytes( "count" ) -, m_pBufferMemory( nullptr ) -, m_nAddrStart( 0 ) -, m_nAddrNumBytesToRead( 0 ) -, m_nAddrOffset( 0 ) +CMICmdCmdDataReadMemoryBytes::CMICmdCmdDataReadMemoryBytes(void) + : m_constStrArgThread("thread") + , m_constStrArgByteOffset("o") + , m_constStrArgAddrStart("address") + , m_constStrArgNumBytes("count") + , m_pBufferMemory(nullptr) + , m_nAddrStart(0) + , m_nAddrNumBytesToRead(0) + , m_nAddrOffset(0) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-read-memory-bytes"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataReadMemoryBytes::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-read-memory-bytes"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataReadMemoryBytes::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataReadMemoryBytes destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataReadMemoryBytes destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes( void ) +CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes(void) { - if( m_pBufferMemory != nullptr ) - { - delete [] m_pBufferMemory; - m_pBufferMemory = nullptr; - } + if (m_pBufferMemory != nullptr) + { + delete[] m_pBufferMemory; + m_pBufferMemory = nullptr; + } } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataReadMemoryBytes::ParseArgs( void ) +bool +CMICmdCmdDataReadMemoryBytes::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgByteOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgAddrStart, true, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNumBytes, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = + bOk && + m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgByteOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgAddrStart, true, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumBytes, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataReadMemoryBytes::Execute( void ) +bool +CMICmdCmdDataReadMemoryBytes::Execute(void) { - CMICMDBASE_GETOPTION( pArgAddrStart, Number, m_constStrArgAddrStart ); - CMICMDBASE_GETOPTION( pArgAddrOffset, Number, m_constStrArgByteOffset ); - CMICMDBASE_GETOPTION( pArgNumBytes, Number, m_constStrArgNumBytes ); - - const MIuint64 nAddrStart = pArgAddrStart->GetValue(); - const MIuint64 nAddrNumBytes = pArgNumBytes->GetValue(); - if( pArgAddrOffset->GetFound() ) - m_nAddrOffset = pArgAddrOffset->GetValue(); - - m_pBufferMemory = new MIuchar[ nAddrNumBytes ]; - if( m_pBufferMemory == nullptr ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_MEMORY_ALLOC_FAILURE ), m_cmdData.strMiCmd.c_str(), nAddrNumBytes ) ); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; - lldb::SBError error; - const MIuint64 nReadBytes = rProcess.ReadMemory( static_cast< lldb::addr_t >( nAddrStart ), (void *) m_pBufferMemory, nAddrNumBytes, error ); - if( nReadBytes != nAddrNumBytes ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK ), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart ) ); - return MIstatus::failure; - } - if( error.Fail() ) - { - lldb::SBStream err; - const bool bOk = error.GetDescription( err ); MIunused( bOk ); - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES ), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart, err.GetData() ) ); - return MIstatus::failure; - } - - m_nAddrStart = nAddrStart; - m_nAddrNumBytesToRead = nAddrNumBytes; - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgAddrStart, Number, m_constStrArgAddrStart); + CMICMDBASE_GETOPTION(pArgAddrOffset, Number, m_constStrArgByteOffset); + CMICMDBASE_GETOPTION(pArgNumBytes, Number, m_constStrArgNumBytes); + + const MIuint64 nAddrStart = pArgAddrStart->GetValue(); + const MIuint64 nAddrNumBytes = pArgNumBytes->GetValue(); + if (pArgAddrOffset->GetFound()) + m_nAddrOffset = pArgAddrOffset->GetValue(); + + m_pBufferMemory = new MIuchar[nAddrNumBytes]; + if (m_pBufferMemory == nullptr) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), m_cmdData.strMiCmd.c_str(), nAddrNumBytes)); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + lldb::SBError error; + const MIuint64 nReadBytes = rProcess.ReadMemory(static_cast(nAddrStart), (void *)m_pBufferMemory, nAddrNumBytes, error); + if (nReadBytes != nAddrNumBytes) + { + SetError( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart)); + return MIstatus::failure; + } + if (error.Fail()) + { + lldb::SBStream err; + const bool bOk = error.GetDescription(err); + MIunused(bOk); + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart, + err.GetData())); + return MIstatus::failure; + } + + m_nAddrStart = nAddrStart; + m_nAddrNumBytesToRead = nAddrNumBytes; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataReadMemoryBytes::Acknowledge( void ) +bool +CMICmdCmdDataReadMemoryBytes::Acknowledge(void) { - // MI: memory=[{begin=\"0x%08x\",offset=\"0x%08x\",end=\"0x%08x\",contents=\" \" }]" - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "0x%08x", m_nAddrStart ) ); - const CMICmnMIValueResult miValueResult( "begin", miValueConst ); - CMICmnMIValueTuple miValueTuple( miValueResult ); - const CMICmnMIValueConst miValueConst2( CMIUtilString::Format( "0x%08x", m_nAddrOffset ) ); - const CMICmnMIValueResult miValueResult2( "offset", miValueConst2 ); - miValueTuple.Add( miValueResult2 ); - const CMICmnMIValueConst miValueConst3( CMIUtilString::Format( "0x%08x", m_nAddrStart + m_nAddrNumBytesToRead ) ); - const CMICmnMIValueResult miValueResult3( "end", miValueConst3 ); - miValueTuple.Add( miValueResult3 ); - - // MI: contents=\" \" - CMIUtilString strContent; - strContent.reserve( (m_nAddrNumBytesToRead << 1) + 1 ); - for( MIuint64 i = 0; i < m_nAddrNumBytesToRead; i ++ ) - { - strContent += CMIUtilString::Format( "%02x", m_pBufferMemory[ i ] ); - } - const CMICmnMIValueConst miValueConst4( strContent ); - const CMICmnMIValueResult miValueResult4( "contents", miValueConst4 ); - miValueTuple.Add( miValueResult4 ); - const CMICmnMIValueList miValueList( miValueTuple ); - const CMICmnMIValueResult miValueResult5( "memory", miValueList ); - - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult5 ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + // MI: memory=[{begin=\"0x%08x\",offset=\"0x%08x\",end=\"0x%08x\",contents=\" \" }]" + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%08x", m_nAddrStart)); + const CMICmnMIValueResult miValueResult("begin", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("0x%08x", m_nAddrOffset)); + const CMICmnMIValueResult miValueResult2("offset", miValueConst2); + miValueTuple.Add(miValueResult2); + const CMICmnMIValueConst miValueConst3(CMIUtilString::Format("0x%08x", m_nAddrStart + m_nAddrNumBytesToRead)); + const CMICmnMIValueResult miValueResult3("end", miValueConst3); + miValueTuple.Add(miValueResult3); + + // MI: contents=\" \" + CMIUtilString strContent; + strContent.reserve((m_nAddrNumBytesToRead << 1) + 1); + for (MIuint64 i = 0; i < m_nAddrNumBytesToRead; i++) + { + strContent += CMIUtilString::Format("%02x", m_pBufferMemory[i]); + } + const CMICmnMIValueConst miValueConst4(strContent); + const CMICmnMIValueResult miValueResult4("contents", miValueConst4); + miValueTuple.Add(miValueResult4); + const CMICmnMIValueList miValueList(miValueTuple); + const CMICmnMIValueResult miValueResult5("memory", miValueList); + + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult5); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdDataReadMemoryBytes::CreateSelf( void ) +CMICmdBase * +CMICmdCmdDataReadMemoryBytes::CreateSelf(void) { - return new CMICmdCmdDataReadMemoryBytes(); + return new CMICmdCmdDataReadMemoryBytes(); } //--------------------------------------------------------------------------------------- @@ -652,78 +685,81 @@ CMICmdBase * CMICmdCmdDataReadMemoryBytes::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataReadMemory constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataReadMemory constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory( void ) +CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory(void) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-read-memory"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataReadMemory::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-read-memory"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataReadMemory::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataReadMemory destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataReadMemory destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory( void ) +CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataReadMemory::Execute( void ) +bool +CMICmdCmdDataReadMemory::Execute(void) { - // Do nothing - command deprecated use "data-read-memory-bytes" command - return MIstatus::success; + // Do nothing - command deprecated use "data-read-memory-bytes" command + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataReadMemory::Acknowledge( void ) +bool +CMICmdCmdDataReadMemory::Acknowledge(void) { - // Command CMICmdCmdSupportListFeatures sends "data-read-memory-bytes" which causes this command not to be called - const CMICmnMIValueConst miValueConst( MIRSRC( IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED ) ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + // Command CMICmdCmdSupportListFeatures sends "data-read-memory-bytes" which causes this command not to be called + const CMICmnMIValueConst miValueConst(MIRSRC(IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED)); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdDataReadMemory::CreateSelf( void ) +CMICmdBase * +CMICmdCmdDataReadMemory::CreateSelf(void) { - return new CMICmdCmdDataReadMemory(); + return new CMICmdCmdDataReadMemory(); } //--------------------------------------------------------------------------------------- @@ -731,121 +767,126 @@ CMICmdBase * CMICmdCmdDataReadMemory::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataListRegisterNames constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataListRegisterNames constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataListRegisterNames::CMICmdCmdDataListRegisterNames( void ) -: m_constStrArgThreadGroup( "thread-group" ) -, m_constStrArgRegNo( "regno" ) -, m_miValueList( true ) +CMICmdCmdDataListRegisterNames::CMICmdCmdDataListRegisterNames(void) + : m_constStrArgThreadGroup("thread-group") + , m_constStrArgRegNo("regno") + , m_miValueList(true) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-list-register-names"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataListRegisterNames::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-list-register-names"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataListRegisterNames::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataReadMemoryBytes destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataReadMemoryBytes destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames( void ) +CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataListRegisterNames::ParseArgs( void ) +bool +CMICmdCmdDataListRegisterNames::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThreadGroup, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgRegNo, false, false, CMICmdArgValListBase::eArgValType_Number ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add( + *(new CMICmdArgValOptionLong(m_constStrArgThreadGroup, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgRegNo, false, false, CMICmdArgValListBase::eArgValType_Number))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataListRegisterNames::Execute( void ) +bool +CMICmdCmdDataListRegisterNames::Execute(void) { - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; - if( !rProcess.IsValid() ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_PROCESS ), m_cmdData.strMiCmd.c_str() ) ); - return MIstatus::failure; - } - - lldb::SBThread thread = rProcess.GetSelectedThread(); - lldb::SBFrame frame = thread.GetSelectedFrame(); - lldb::SBValueList registers = frame.GetRegisters(); - const MIuint nRegisters = registers.GetSize(); - for( MIuint i = 0; i < nRegisters; i++ ) - { - lldb::SBValue value = registers.GetValueAtIndex( i ); - const MIuint nRegChildren = value.GetNumChildren(); - for( MIuint j = 0; j < nRegChildren; j++ ) - { - lldb::SBValue value2 = value.GetChildAtIndex( j ); - if( value2.IsValid() ) - { - const CMICmnMIValueConst miValueConst( CMICmnLLDBUtilSBValue( value2 ).GetName() ); - m_miValueList.Add( miValueConst ); - } - } - } - - return MIstatus::success; + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + if (!rProcess.IsValid()) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + lldb::SBThread thread = rProcess.GetSelectedThread(); + lldb::SBFrame frame = thread.GetSelectedFrame(); + lldb::SBValueList registers = frame.GetRegisters(); + const MIuint nRegisters = registers.GetSize(); + for (MIuint i = 0; i < nRegisters; i++) + { + lldb::SBValue value = registers.GetValueAtIndex(i); + const MIuint nRegChildren = value.GetNumChildren(); + for (MIuint j = 0; j < nRegChildren; j++) + { + lldb::SBValue value2 = value.GetChildAtIndex(j); + if (value2.IsValid()) + { + const CMICmnMIValueConst miValueConst(CMICmnLLDBUtilSBValue(value2).GetName()); + m_miValueList.Add(miValueConst); + } + } + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataListRegisterNames::Acknowledge( void ) +bool +CMICmdCmdDataListRegisterNames::Acknowledge(void) { - const CMICmnMIValueResult miValueResult( "register-names", m_miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + const CMICmnMIValueResult miValueResult("register-names", m_miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdDataListRegisterNames::CreateSelf( void ) +CMICmdBase * +CMICmdCmdDataListRegisterNames::CreateSelf(void) { - return new CMICmdCmdDataListRegisterNames(); + return new CMICmdCmdDataListRegisterNames(); } //--------------------------------------------------------------------------------------- @@ -853,176 +894,182 @@ CMICmdBase * CMICmdCmdDataListRegisterNames::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataListRegisterValues constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataListRegisterValues constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataListRegisterValues::CMICmdCmdDataListRegisterValues( void ) -: m_constStrArgThread( "thread" ) -, m_constStrArgSkip( "skip-unavailable" ) -, m_constStrArgFormat( "fmt" ) -, m_constStrArgRegNo( "regno" ) -, m_miValueList( true ) -, m_pProcess( nullptr ) +CMICmdCmdDataListRegisterValues::CMICmdCmdDataListRegisterValues(void) + : m_constStrArgThread("thread") + , m_constStrArgSkip("skip-unavailable") + , m_constStrArgFormat("fmt") + , m_constStrArgRegNo("regno") + , m_miValueList(true) + , m_pProcess(nullptr) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-list-register-values"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataListRegisterValues::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-list-register-values"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataListRegisterValues::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataListRegisterValues destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataListRegisterValues destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues( void ) +CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataListRegisterValues::ParseArgs( void ) +bool +CMICmdCmdDataListRegisterValues::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgSkip, false, false ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgFormat, true, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgRegNo, false, true, CMICmdArgValListBase::eArgValType_Number ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgSkip, false, false))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgFormat, true, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgRegNo, false, true, CMICmdArgValListBase::eArgValType_Number))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataListRegisterValues::Execute( void ) +bool +CMICmdCmdDataListRegisterValues::Execute(void) { - CMICMDBASE_GETOPTION( pArgFormat, String, m_constStrArgFormat ); - CMICMDBASE_GETOPTION( pArgRegNo, ListOfN, m_constStrArgRegNo ); - - const CMIUtilString & rStrFormat( pArgFormat->GetValue() ); - if( rStrFormat.length() != 1 ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_FORMAT_TYPE ), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str() ) ); - return MIstatus::failure; - } - const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e eFormat = CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar( rStrFormat[ 0 ] ); - if( eFormat == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_FORMAT_TYPE ), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str() ) ); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; - if( !rProcess.IsValid() ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_PROCESS ), m_cmdData.strMiCmd.c_str() ) ); - return MIstatus::failure; - } - m_pProcess = &rProcess; - - const CMICmdArgValListBase::VecArgObjPtr_t & rVecRegNo( pArgRegNo->GetExpectedOptions() ); - CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin(); - while( it != rVecRegNo.end() ) - { - const CMICmdArgValNumber * pRegNo = static_cast< CMICmdArgValNumber * >( *it ); - const MIuint nReg = pRegNo->GetValue(); - lldb::SBValue regValue = GetRegister( nReg ); - const CMIUtilString strRegValue( CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted( regValue, eFormat ) ); - - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%u", nReg ) ); - const CMICmnMIValueResult miValueResult( "number", miValueConst ); - CMICmnMIValueTuple miValueTuple( miValueResult ); - const CMICmnMIValueConst miValueConst2( strRegValue ); - const CMICmnMIValueResult miValueResult2( "value", miValueConst2 ); - miValueTuple.Add( miValueResult2 ); - m_miValueList.Add( miValueTuple ); - - // Next - ++it; - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgFormat, String, m_constStrArgFormat); + CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo); + + const CMIUtilString &rStrFormat(pArgFormat->GetValue()); + if (rStrFormat.length() != 1) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str())); + return MIstatus::failure; + } + const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e eFormat = CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(rStrFormat[0]); + if (eFormat == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + if (!rProcess.IsValid()) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + m_pProcess = &rProcess; + + const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(pArgRegNo->GetExpectedOptions()); + CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin(); + while (it != rVecRegNo.end()) + { + const CMICmdArgValNumber *pRegNo = static_cast(*it); + const MIuint nReg = pRegNo->GetValue(); + lldb::SBValue regValue = GetRegister(nReg); + const CMIUtilString strRegValue(CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(regValue, eFormat)); + + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%u", nReg)); + const CMICmnMIValueResult miValueResult("number", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueConst miValueConst2(strRegValue); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + m_miValueList.Add(miValueTuple); + + // Next + ++it; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataListRegisterValues::Acknowledge( void ) +bool +CMICmdCmdDataListRegisterValues::Acknowledge(void) { - const CMICmnMIValueResult miValueResult( "register-values", m_miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + const CMICmnMIValueResult miValueResult("register-values", m_miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdDataListRegisterValues::CreateSelf( void ) +CMICmdBase * +CMICmdCmdDataListRegisterValues::CreateSelf(void) { - return new CMICmdCmdDataListRegisterValues(); + return new CMICmdCmdDataListRegisterValues(); } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Method. -// Args: None. -// Return: lldb::SBValue - LLDB SBValue object. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Method. +// Args: None. +// Return: lldb::SBValue - LLDB SBValue object. +// Throws: None. //-- -lldb::SBValue CMICmdCmdDataListRegisterValues::GetRegister( const MIuint vRegisterIndex ) const +lldb::SBValue +CMICmdCmdDataListRegisterValues::GetRegister(const MIuint vRegisterIndex) const { - lldb::SBThread thread = m_pProcess->GetSelectedThread(); - lldb::SBFrame frame = thread.GetSelectedFrame(); - lldb::SBValueList registers = frame.GetRegisters(); - const MIuint nRegisters = registers.GetSize(); - for( MIuint i = 0; i < nRegisters; i++ ) - { - lldb::SBValue value = registers.GetValueAtIndex( i ); - const MIuint nRegChildren = value.GetNumChildren(); - if( nRegChildren > 0 ) - { - lldb::SBValue value2 = value.GetChildAtIndex( vRegisterIndex ); - if( value2.IsValid() ) - { - return value2; - } - } - } - - return lldb::SBValue(); + lldb::SBThread thread = m_pProcess->GetSelectedThread(); + lldb::SBFrame frame = thread.GetSelectedFrame(); + lldb::SBValueList registers = frame.GetRegisters(); + const MIuint nRegisters = registers.GetSize(); + for (MIuint i = 0; i < nRegisters; i++) + { + lldb::SBValue value = registers.GetValueAtIndex(i); + const MIuint nRegChildren = value.GetNumChildren(); + if (nRegChildren > 0) + { + lldb::SBValue value2 = value.GetChildAtIndex(vRegisterIndex); + if (value2.IsValid()) + { + return value2; + } + } + } + + return lldb::SBValue(); } //--------------------------------------------------------------------------------------- @@ -1030,78 +1077,81 @@ lldb::SBValue CMICmdCmdDataListRegisterValues::GetRegister( const MIuint vRegist //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataListRegisterChanged constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataListRegisterChanged constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged( void ) +CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged(void) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-list-changed-registers"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataListRegisterChanged::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-list-changed-registers"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataListRegisterChanged::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataListRegisterChanged destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataListRegisterChanged destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged( void ) +CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataListRegisterChanged::Execute( void ) +bool +CMICmdCmdDataListRegisterChanged::Execute(void) { - // Do nothing - - return MIstatus::success; + // Do nothing + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataListRegisterChanged::Acknowledge( void ) +bool +CMICmdCmdDataListRegisterChanged::Acknowledge(void) { - const CMICmnMIValueConst miValueConst( MIRSRC( IDS_WORD_NOT_IMPLEMENTED ) ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; + const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED)); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdDataListRegisterChanged::CreateSelf( void ) +CMICmdBase * +CMICmdCmdDataListRegisterChanged::CreateSelf(void) { - return new CMICmdCmdDataListRegisterChanged(); + return new CMICmdCmdDataListRegisterChanged(); } //--------------------------------------------------------------------------------------- @@ -1109,109 +1159,112 @@ CMICmdBase * CMICmdCmdDataListRegisterChanged::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataWriteMemoryBytes constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataWriteMemoryBytes constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataWriteMemoryBytes::CMICmdCmdDataWriteMemoryBytes( void ) -: m_constStrArgThread( "thread" ) -, m_constStrArgAddr( "address" ) -, m_constStrArgContents( "contents" ) -, m_constStrArgCount( "count" ) -, m_nAddr( 0 ) -, m_nCount( 0 ) +CMICmdCmdDataWriteMemoryBytes::CMICmdCmdDataWriteMemoryBytes(void) + : m_constStrArgThread("thread") + , m_constStrArgAddr("address") + , m_constStrArgContents("contents") + , m_constStrArgCount("count") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-write-memory-bytes"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataWriteMemoryBytes::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-write-memory-bytes"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataWriteMemoryBytes::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataWriteMemoryBytes destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataWriteMemoryBytes destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes( void ) +CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataWriteMemoryBytes::ParseArgs( void ) +bool +CMICmdCmdDataWriteMemoryBytes::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgAddr, true, true, false, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgContents, true, true, true, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgCount, false, true, false, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgAddr, true, true, false, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgContents, true, true, true, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgCount, false, true, false, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataWriteMemoryBytes::Execute( void ) +bool +CMICmdCmdDataWriteMemoryBytes::Execute(void) { - // Do nothing - not reproduceable (yet) in Eclipse - //CMICMDBASE_GETOPTION( pArgOffset, OptionShort, m_constStrArgOffset ); - //CMICMDBASE_GETOPTION( pArgAddr, String, m_constStrArgAddr ); - //CMICMDBASE_GETOPTION( pArgNumber, String, m_constStrArgNumber ); - //CMICMDBASE_GETOPTION( pArgContents, String, m_constStrArgContents ); - // - // Numbers extracts as string types as they could be hex numbers - // '&' is not recognised and so has to be removed - - return MIstatus::success; + // Do nothing - not reproduceable (yet) in Eclipse + // CMICMDBASE_GETOPTION( pArgOffset, OptionShort, m_constStrArgOffset ); + // CMICMDBASE_GETOPTION( pArgAddr, String, m_constStrArgAddr ); + // CMICMDBASE_GETOPTION( pArgNumber, String, m_constStrArgNumber ); + // CMICMDBASE_GETOPTION( pArgContents, String, m_constStrArgContents ); + // + // Numbers extracts as string types as they could be hex numbers + // '&' is not recognised and so has to be removed + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataWriteMemoryBytes::Acknowledge( void ) +bool +CMICmdCmdDataWriteMemoryBytes::Acknowledge(void) { - const CMICmnMIValueConst miValueConst( MIRSRC( IDS_WORD_NOT_IMPLEMENTED ) ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; + const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED)); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdDataWriteMemoryBytes::CreateSelf( void ) +CMICmdBase * +CMICmdCmdDataWriteMemoryBytes::CreateSelf(void) { - return new CMICmdCmdDataWriteMemoryBytes(); + return new CMICmdCmdDataWriteMemoryBytes(); } //--------------------------------------------------------------------------------------- @@ -1219,147 +1272,155 @@ CMICmdBase * CMICmdCmdDataWriteMemoryBytes::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataWriteMemory constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataWriteMemory constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataWriteMemory::CMICmdCmdDataWriteMemory( void ) -: m_constStrArgThread( "thread" ) -, m_constStrArgOffset( "o" ) -, m_constStrArgAddr( "address" ) -, m_constStrArgD( "d" ) -, m_constStrArgNumber( "a number" ) -, m_constStrArgContents( "contents" ) -, m_nAddr( 0 ) -, m_nCount( 0 ) -, m_pBufferMemory( nullptr ) +CMICmdCmdDataWriteMemory::CMICmdCmdDataWriteMemory(void) + : m_constStrArgThread("thread") + , m_constStrArgOffset("o") + , m_constStrArgAddr("address") + , m_constStrArgD("d") + , m_constStrArgNumber("a number") + , m_constStrArgContents("contents") + , m_nAddr(0) + , m_nCount(0) + , m_pBufferMemory(nullptr) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-write-memory"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataWriteMemory::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-write-memory"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataWriteMemory::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdDataWriteMemory destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdDataWriteMemory destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory( void ) +CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory(void) { - if( m_pBufferMemory != nullptr ) - { - delete [] m_pBufferMemory; - m_pBufferMemory = nullptr; - } + if (m_pBufferMemory != nullptr) + { + delete[] m_pBufferMemory; + m_pBufferMemory = nullptr; + } } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataWriteMemory::ParseArgs( void ) +bool +CMICmdCmdDataWriteMemory::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgAddr, true, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgD, true, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNumber, true, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgContents, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && + m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgAddr, true, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgD, true, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumber, true, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgContents, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataWriteMemory::Execute( void ) +bool +CMICmdCmdDataWriteMemory::Execute(void) { - CMICMDBASE_GETOPTION( pArgOffset, OptionShort, m_constStrArgOffset ); - CMICMDBASE_GETOPTION( pArgAddr, Number, m_constStrArgAddr ); - CMICMDBASE_GETOPTION( pArgNumber, Number, m_constStrArgNumber ); - CMICMDBASE_GETOPTION( pArgContents, Number, m_constStrArgContents ); - - MIuint nAddrOffset = 0; - if( pArgOffset->GetFound() && !pArgOffset->GetExpectedOption< CMICmdArgValNumber, MIuint>( nAddrOffset ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_VALIDATION_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgAddr.c_str() ) ); - return MIstatus::failure; - } - m_nAddr = pArgAddr->GetValue(); - m_nCount = pArgNumber->GetValue(); - const MIuint64 nValue = pArgContents->GetValue(); - - m_pBufferMemory = new MIuchar [ m_nCount ]; - if( m_pBufferMemory == nullptr ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_MEMORY_ALLOC_FAILURE ), m_cmdData.strMiCmd.c_str(), m_nCount ) ); - return MIstatus::failure; - } - *m_pBufferMemory = static_cast< MIchar >( nValue ); - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; - lldb::SBError error; - lldb::addr_t addr = static_cast< lldb::addr_t >( m_nAddr + nAddrOffset ); - const size_t nBytesWritten = rProcess.WriteMemory( addr, (const void *) m_pBufferMemory, (size_t) m_nCount, error ); - if( nBytesWritten != static_cast< size_t >( m_nCount ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK ), m_cmdData.strMiCmd.c_str(), m_nCount, addr ) ); - return MIstatus::failure; - } - if( error.Fail() ) - { - lldb::SBStream err; - const bool bOk = error.GetDescription( err ); MIunused( bOk ); - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES ), m_cmdData.strMiCmd.c_str(), m_nCount, addr, err.GetData() ) ); - return MIstatus::failure; - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgOffset, OptionShort, m_constStrArgOffset); + CMICMDBASE_GETOPTION(pArgAddr, Number, m_constStrArgAddr); + CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNumber); + CMICMDBASE_GETOPTION(pArgContents, Number, m_constStrArgContents); + + MIuint nAddrOffset = 0; + if (pArgOffset->GetFound() && !pArgOffset->GetExpectedOption(nAddrOffset)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddr.c_str())); + return MIstatus::failure; + } + m_nAddr = pArgAddr->GetValue(); + m_nCount = pArgNumber->GetValue(); + const MIuint64 nValue = pArgContents->GetValue(); + + m_pBufferMemory = new MIuchar[m_nCount]; + if (m_pBufferMemory == nullptr) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), m_cmdData.strMiCmd.c_str(), m_nCount)); + return MIstatus::failure; + } + *m_pBufferMemory = static_cast(nValue); + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + lldb::SBError error; + lldb::addr_t addr = static_cast(m_nAddr + nAddrOffset); + const size_t nBytesWritten = rProcess.WriteMemory(addr, (const void *)m_pBufferMemory, (size_t)m_nCount, error); + if (nBytesWritten != static_cast(m_nCount)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK), m_cmdData.strMiCmd.c_str(), m_nCount, addr)); + return MIstatus::failure; + } + if (error.Fail()) + { + lldb::SBStream err; + const bool bOk = error.GetDescription(err); + MIunused(bOk); + SetError( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES), m_cmdData.strMiCmd.c_str(), m_nCount, addr, err.GetData())); + return MIstatus::failure; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdDataWriteMemory::Acknowledge( void ) +bool +CMICmdCmdDataWriteMemory::Acknowledge(void) { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done ); - m_miResultRecord = miRecordResult; + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdDataWriteMemory::CreateSelf( void ) +CMICmdBase * +CMICmdCmdDataWriteMemory::CreateSelf(void) { - return new CMICmdCmdDataWriteMemory(); + return new CMICmdCmdDataWriteMemory(); } diff --git a/tools/lldb-mi/MICmdCmdData.h b/tools/lldb-mi/MICmdCmdData.h index c1501de3918f..74ceeb8581b9 100644 --- a/tools/lldb-mi/MICmdCmdData.h +++ b/tools/lldb-mi/MICmdCmdData.h @@ -8,32 +8,32 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdData.h +// File: MICmdCmdData.h // -// Overview: CMICmdCmdDataEvaluateExpression interface. -// CMICmdCmdDataDisassemble interface. -// CMICmdCmdDataReadMemoryBytes interface. -// CMICmdCmdDataReadMemory interface. -// CMICmdCmdDataListRegisterNames interface. -// CMICmdCmdDataListRegisterValues interface. -// CMICmdCmdDataListRegisterChanged interface. -// CMICmdCmdDataWriteMemoryBytes interface. -// CMICmdCmdDataWriteMemory interface. +// Overview: CMICmdCmdDataEvaluateExpression interface. +// CMICmdCmdDataDisassemble interface. +// CMICmdCmdDataReadMemoryBytes interface. +// CMICmdCmdDataReadMemory interface. +// CMICmdCmdDataListRegisterNames interface. +// CMICmdCmdDataListRegisterValues interface. +// CMICmdCmdDataListRegisterChanged interface. +// CMICmdCmdDataWriteMemoryBytes interface. +// CMICmdCmdDataWriteMemory interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -44,331 +44,329 @@ #include "MICmnMIValueList.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "data-evaluate-expression". -// Gotchas: None. -// Authors: Illya Rudkin 26/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "data-evaluate-expression". +// Gotchas: None. +// Authors: Illya Rudkin 26/03/2014. +// Changes: None. //-- class CMICmdCmdDataEvaluateExpression : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdDataEvaluateExpression( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdDataEvaluateExpression( void ); - -// Methods: -private: - bool HaveInvalidCharacterInExpression( const CMIUtilString & vrExpr, MIchar & vrwInvalidChar ); - -// Attributes: -private: - bool m_bExpressionValid; // True = yes is valid, false = not valid - bool m_bEvaluatedExpression; // True = yes is expression evaluated, false = failed - CMIUtilString m_strValue; - CMICmnMIValueTuple m_miValueTuple; - bool m_bCompositeVarType; // True = yes composite type, false = internal type - bool m_bFoundInvalidChar; // True = yes found unexpected character in the expression, false = all ok - MIchar m_cExpressionInvalidChar; - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command. - const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option. Not handled by command. - const CMIUtilString m_constStrArgExpr; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdDataEvaluateExpression(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdDataEvaluateExpression(void); + + // Methods: + private: + bool HaveInvalidCharacterInExpression(const CMIUtilString &vrExpr, MIchar &vrwInvalidChar); + + // Attributes: + private: + bool m_bExpressionValid; // True = yes is valid, false = not valid + bool m_bEvaluatedExpression; // True = yes is expression evaluated, false = failed + CMIUtilString m_strValue; + CMICmnMIValueTuple m_miValueTuple; + bool m_bCompositeVarType; // True = yes composite type, false = internal type + bool m_bFoundInvalidChar; // True = yes found unexpected character in the expression, false = all ok + MIchar m_cExpressionInvalidChar; + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command. + const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option. Not handled by command. + const CMIUtilString m_constStrArgExpr; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "data-disassemble". -// Gotchas: None. -// Authors: Illya Rudkin 19/05/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "data-disassemble". +// Gotchas: None. +// Authors: Illya Rudkin 19/05/2014. +// Changes: None. //-- class CMICmdCmdDataDisassemble : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdDataDisassemble( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdDataDisassemble( void ); - -// Attributes: -private: - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command. - const CMIUtilString m_constStrArgAddrStart; // MI spec non mandatory, *this command mandatory - const CMIUtilString m_constStrArgAddrEnd; // MI spec non mandatory, *this command mandatory - const CMIUtilString m_constStrArgConsume; - const CMIUtilString m_constStrArgMode; - CMICmnMIValueList m_miValueList; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdDataDisassemble(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdDataDisassemble(void); + + // Attributes: + private: + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command. + const CMIUtilString m_constStrArgAddrStart; // MI spec non mandatory, *this command mandatory + const CMIUtilString m_constStrArgAddrEnd; // MI spec non mandatory, *this command mandatory + const CMIUtilString m_constStrArgConsume; + const CMIUtilString m_constStrArgMode; + CMICmnMIValueList m_miValueList; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "data-read-memory-bytes". -// Gotchas: None. -// Authors: Illya Rudkin 20/05/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "data-read-memory-bytes". +// Gotchas: None. +// Authors: Illya Rudkin 20/05/2014. +// Changes: None. //-- class CMICmdCmdDataReadMemoryBytes : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdDataReadMemoryBytes( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdDataReadMemoryBytes( void ); - -// Attributes: -private: - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command. - const CMIUtilString m_constStrArgByteOffset; - const CMIUtilString m_constStrArgAddrStart; - const CMIUtilString m_constStrArgNumBytes; - MIuchar * m_pBufferMemory; - MIuint64 m_nAddrStart; - MIuint64 m_nAddrNumBytesToRead; - MIuint64 m_nAddrOffset; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdDataReadMemoryBytes(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdDataReadMemoryBytes(void); + + // Attributes: + private: + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command. + const CMIUtilString m_constStrArgByteOffset; + const CMIUtilString m_constStrArgAddrStart; + const CMIUtilString m_constStrArgNumBytes; + MIuchar *m_pBufferMemory; + MIuint64 m_nAddrStart; + MIuint64 m_nAddrNumBytesToRead; + MIuint64 m_nAddrOffset; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "data-read-memory". -// Gotchas: None. -// Authors: Illya Rudkin 21/05/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "data-read-memory". +// Gotchas: None. +// Authors: Illya Rudkin 21/05/2014. +// Changes: None. //-- class CMICmdCmdDataReadMemory : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdDataReadMemory( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdDataReadMemory( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdDataReadMemory(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdDataReadMemory(void); }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "data-list-register-names". -// Gotchas: None. -// Authors: Illya Rudkin 21/05/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "data-list-register-names". +// Gotchas: None. +// Authors: Illya Rudkin 21/05/2014. +// Changes: None. //-- class CMICmdCmdDataListRegisterNames : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdDataListRegisterNames( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdDataListRegisterNames( void ); - -// Attributes: -private: - const CMIUtilString m_constStrArgThreadGroup; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgRegNo; // Not handled by *this command - CMICmnMIValueList m_miValueList; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdDataListRegisterNames(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdDataListRegisterNames(void); + + // Attributes: + private: + const CMIUtilString m_constStrArgThreadGroup; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgRegNo; // Not handled by *this command + CMICmnMIValueList m_miValueList; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "data-list-register-values". -// Gotchas: None. -// Authors: Illya Rudkin 21/05/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "data-list-register-values". +// Gotchas: None. +// Authors: Illya Rudkin 21/05/2014. +// Changes: None. //-- class CMICmdCmdDataListRegisterValues : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdDataListRegisterValues( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdDataListRegisterValues( void ); - -// Methods: -private: - lldb::SBValue GetRegister( const MIuint vRegisterIndex ) const; - -// Attributes: -private: - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgSkip; // Not handled by *this command - const CMIUtilString m_constStrArgFormat; - const CMIUtilString m_constStrArgRegNo; - CMICmnMIValueList m_miValueList; - lldb::SBProcess * m_pProcess; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdDataListRegisterValues(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdDataListRegisterValues(void); + + // Methods: + private: + lldb::SBValue GetRegister(const MIuint vRegisterIndex) const; + + // Attributes: + private: + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgSkip; // Not handled by *this command + const CMIUtilString m_constStrArgFormat; + const CMIUtilString m_constStrArgRegNo; + CMICmnMIValueList m_miValueList; + lldb::SBProcess *m_pProcess; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "data-list-changed-registers". -// Gotchas: None. -// Authors: Illya Rudkin 22/05/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "data-list-changed-registers". +// Gotchas: None. +// Authors: Illya Rudkin 22/05/2014. +// Changes: None. //-- class CMICmdCmdDataListRegisterChanged : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdDataListRegisterChanged( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdDataListRegisterChanged( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdDataListRegisterChanged(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdDataListRegisterChanged(void); }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "data-read-memory-bytes". -// Gotchas: None. -// Authors: Illya Rudkin 30/05/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "data-read-memory-bytes". +// Gotchas: None. +// Authors: Illya Rudkin 30/05/2014. +// Changes: None. //-- class CMICmdCmdDataWriteMemoryBytes : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdDataWriteMemoryBytes( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdDataWriteMemoryBytes( void ); - -// Attributes: -private: - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command. - const CMIUtilString m_constStrArgAddr; - const CMIUtilString m_constStrArgContents; - const CMIUtilString m_constStrArgCount; - MIuint64 m_nAddr; - CMIUtilString m_strContents; - MIuint64 m_nCount; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdDataWriteMemoryBytes(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdDataWriteMemoryBytes(void); + + // Attributes: + private: + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command. + const CMIUtilString m_constStrArgAddr; + const CMIUtilString m_constStrArgContents; + const CMIUtilString m_constStrArgCount; + CMIUtilString m_strContents; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "data-read-memory". -// Not specified in MI spec but Eclipse gives *this command. -// Gotchas: None. -// Authors: Illya Rudkin 02/05/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "data-read-memory". +// Not specified in MI spec but Eclipse gives *this command. +// Gotchas: None. +// Authors: Illya Rudkin 02/05/2014. +// Changes: None. //-- class CMICmdCmdDataWriteMemory : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdDataWriteMemory( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdDataWriteMemory( void ); - -// Attributes: -private: - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command. - const CMIUtilString m_constStrArgOffset; // Not specified in MI spec but Eclipse gives this option. - const CMIUtilString m_constStrArgAddr; // Not specified in MI spec but Eclipse gives this option. - const CMIUtilString m_constStrArgD; // Not specified in MI spec but Eclipse gives this option. - const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option. - const CMIUtilString m_constStrArgContents; // Not specified in MI spec but Eclipse gives this option. - MIuint64 m_nAddr; - CMIUtilString m_strContents; - MIuint64 m_nCount; - MIuchar * m_pBufferMemory; -}; \ No newline at end of file + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdDataWriteMemory(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdDataWriteMemory(void); + + // Attributes: + private: + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command. + const CMIUtilString m_constStrArgOffset; // Not specified in MI spec but Eclipse gives this option. + const CMIUtilString m_constStrArgAddr; // Not specified in MI spec but Eclipse gives this option. + const CMIUtilString m_constStrArgD; // Not specified in MI spec but Eclipse gives this option. + const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option. + const CMIUtilString m_constStrArgContents; // Not specified in MI spec but Eclipse gives this option. + MIuint64 m_nAddr; + CMIUtilString m_strContents; + MIuint64 m_nCount; + MIuchar *m_pBufferMemory; +}; diff --git a/tools/lldb-mi/MICmdCmdEnviro.cpp b/tools/lldb-mi/MICmdCmdEnviro.cpp index b47327af9406..a4369ab3a990 100644 --- a/tools/lldb-mi/MICmdCmdEnviro.cpp +++ b/tools/lldb-mi/MICmdCmdEnviro.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdEnviro.cpp +// File: MICmdCmdEnviro.cpp // -// Overview: CMICmdCmdEnvironmentCd implementation. +// Overview: CMICmdCmdEnvironmentCd implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -28,116 +28,120 @@ #include "MICmdArgValFile.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdEnvironmentCd constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdEnvironmentCd constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdEnvironmentCd::CMICmdCmdEnvironmentCd( void ) -: m_constStrArgNamePathDir( "pathdir" ) +CMICmdCmdEnvironmentCd::CMICmdCmdEnvironmentCd(void) + : m_constStrArgNamePathDir("pathdir") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "environment-cd"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdEnvironmentCd::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "environment-cd"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdEnvironmentCd::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdEnvironmentCd destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdEnvironmentCd destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdEnvironmentCd::~CMICmdCmdEnvironmentCd( void ) +CMICmdCmdEnvironmentCd::~CMICmdCmdEnvironmentCd(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdEnvironmentCd::ParseArgs( void ) +bool +CMICmdCmdEnvironmentCd::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValFile( m_constStrArgNamePathDir, true, true ) ) ); - CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValFile(m_constStrArgNamePathDir, true, true))); + CMICmdArgContext argCntxt(m_cmdData.strMiCmdOption); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdEnvironmentCd::Execute( void ) +bool +CMICmdCmdEnvironmentCd::Execute(void) { - CMICMDBASE_GETOPTION( pArgPathDir, File, m_constStrArgNamePathDir ); - const CMIUtilString & strWkDir( pArgPathDir->GetValue() ); - CMICmnLLDBDebugger & rDbg( CMICmnLLDBDebugger::Instance() ); - lldb::SBDebugger & rLldbDbg = rDbg.GetTheDebugger(); - bool bOk = rLldbDbg.SetCurrentPlatformSDKRoot( strWkDir.c_str() ); - if( bOk ) - { - const CMIUtilString & rStrKeyWkDir( m_rLLDBDebugSessionInfo.m_constStrSharedDataKeyWkDir ); - if( !m_rLLDBDebugSessionInfo.SharedDataAdd< CMIUtilString >( rStrKeyWkDir, strWkDir ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_DBGSESSION_ERR_SHARED_DATA_ADD ), m_cmdData.strMiCmd.c_str(), rStrKeyWkDir.c_str() ) ); - bOk = MIstatus::failure; - } - } - else - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_FNFAILED ), m_cmdData.strMiCmd.c_str(), "SetCurrentPlatformSDKRoot()" ) ); + CMICMDBASE_GETOPTION(pArgPathDir, File, m_constStrArgNamePathDir); + const CMIUtilString &strWkDir(pArgPathDir->GetValue()); + CMICmnLLDBDebugger &rDbg(CMICmnLLDBDebugger::Instance()); + lldb::SBDebugger &rLldbDbg = rDbg.GetTheDebugger(); + bool bOk = rLldbDbg.SetCurrentPlatformSDKRoot(strWkDir.c_str()); + if (bOk) + { + const CMIUtilString &rStrKeyWkDir(m_rLLDBDebugSessionInfo.m_constStrSharedDataKeyWkDir); + if (!m_rLLDBDebugSessionInfo.SharedDataAdd(rStrKeyWkDir, strWkDir)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), m_cmdData.strMiCmd.c_str(), rStrKeyWkDir.c_str())); + bOk = MIstatus::failure; + } + } + else + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), m_cmdData.strMiCmd.c_str(), "SetCurrentPlatformSDKRoot()")); - return bOk; + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdEnvironmentCd::Acknowledge( void ) +bool +CMICmdCmdEnvironmentCd::Acknowledge(void) { - const CMIUtilString & rStrKeyWkDir( m_rLLDBDebugSessionInfo.m_constStrSharedDataKeyWkDir ); - CMIUtilString strWkDir; - const bool bOk = m_rLLDBDebugSessionInfo.SharedDataRetrieve< CMIUtilString >( rStrKeyWkDir, strWkDir ); - if( bOk ) - { - const CMICmnMIValueConst miValueConst( strWkDir ); - const CMICmnMIValueResult miValueResult( "path", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } + const CMIUtilString &rStrKeyWkDir(m_rLLDBDebugSessionInfo.m_constStrSharedDataKeyWkDir); + CMIUtilString strWkDir; + const bool bOk = m_rLLDBDebugSessionInfo.SharedDataRetrieve(rStrKeyWkDir, strWkDir); + if (bOk) + { + const CMICmnMIValueConst miValueConst(strWkDir); + const CMICmnMIValueResult miValueResult("path", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_SHARED_DATA_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), rStrKeyWkDir.c_str() ) ); - return MIstatus::failure; + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SHARED_DATA_NOT_FOUND), m_cmdData.strMiCmd.c_str(), rStrKeyWkDir.c_str())); + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdEnvironmentCd::CreateSelf( void ) +CMICmdBase * +CMICmdCmdEnvironmentCd::CreateSelf(void) { - return new CMICmdCmdEnvironmentCd(); + return new CMICmdCmdEnvironmentCd(); } diff --git a/tools/lldb-mi/MICmdCmdEnviro.h b/tools/lldb-mi/MICmdCmdEnviro.h index efbe89238218..9a223beb91b0 100644 --- a/tools/lldb-mi/MICmdCmdEnviro.h +++ b/tools/lldb-mi/MICmdCmdEnviro.h @@ -8,24 +8,24 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdEnviro.h +// File: MICmdCmdEnviro.h // -// Overview: CMICmdCmdEnvironmentCd interface. +// Overview: CMICmdCmdEnvironmentCd interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -36,34 +36,33 @@ #include "MICmnMIValueList.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "environment-cd". -// Gotchas: None. -// Authors: Illya Rudkin 03/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "environment-cd". +// Gotchas: None. +// Authors: Illya Rudkin 03/03/2014. +// Changes: None. //-- class CMICmdCmdEnvironmentCd : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdEnvironmentCd( void ); + // Methods: + public: + /* ctor */ CMICmdCmdEnvironmentCd(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdEnvironmentCd( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdEnvironmentCd(void); -// Attributes: -private: - const CMIUtilString m_constStrArgNamePathDir; + // Attributes: + private: + const CMIUtilString m_constStrArgNamePathDir; }; - diff --git a/tools/lldb-mi/MICmdCmdExec.cpp b/tools/lldb-mi/MICmdCmdExec.cpp index c0ec25d701b7..9e1224363f5d 100644 --- a/tools/lldb-mi/MICmdCmdExec.cpp +++ b/tools/lldb-mi/MICmdCmdExec.cpp @@ -8,22 +8,22 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdExec.cpp +// File: MICmdCmdExec.cpp // -// Overview: CMICmdCmdExecRun implementation. -// CMICmdCmdExecContinue implementation. -// CMICmdCmdExecNext implementation. -// CMICmdCmdExecStep implementation. -// CMICmdCmdExecNextInstruction implementation. -// CMICmdCmdExecStepInstruction implementation. -// CMICmdCmdExecFinish implementation. -// CMICmdCmdExecInterrupt implementation. +// Overview: CMICmdCmdExecRun implementation. +// CMICmdCmdExecContinue implementation. +// CMICmdCmdExecNext implementation. +// CMICmdCmdExecStep implementation. +// CMICmdCmdExecNextInstruction implementation. +// CMICmdCmdExecStepInstruction implementation. +// CMICmdCmdExecFinish implementation. +// CMICmdCmdExecInterrupt implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third Party Headers: @@ -49,120 +49,122 @@ #include "MICmnMIOutOfBandRecord.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecRun constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecRun constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecRun::CMICmdCmdExecRun( void ) +CMICmdCmdExecRun::CMICmdCmdExecRun(void) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-run"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecRun::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-run"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecRun::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecRun destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecRun destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecRun::~CMICmdCmdExecRun( void ) +CMICmdCmdExecRun::~CMICmdCmdExecRun(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecRun::Execute( void ) +bool +CMICmdCmdExecRun::Execute(void) { - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBError error; lldb::SBStream errMsg; uint32_t launch_flags = lldb::LaunchFlags::eLaunchFlagDebug; - lldb::SBProcess process = rSessionInfo.m_lldbTarget.Launch (rSessionInfo.m_rLlldbListener, - nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, launch_flags, false, error); + lldb::SBProcess process = rSessionInfo.m_lldbTarget.Launch(rSessionInfo.m_rLlldbListener, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, launch_flags, false, error); - if( (!process.IsValid()) || (error.Fail()) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_PROCESS ), m_cmdData.strMiCmd.c_str(), errMsg.GetData() ) ); - return MIstatus::failure; - } + if ((!process.IsValid()) || (error.Fail())) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str(), errMsg.GetData())); + return MIstatus::failure; + } - // Save the process in the session info - rSessionInfo.m_lldbProcess = process; + // Save the process in the session info + rSessionInfo.m_lldbProcess = process; - if( !CMIDriver::Instance().SetDriverStateRunningDebugging() ) - { - const CMIUtilString & rErrMsg( CMIDriver::Instance().GetErrorDescription() ); - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_SET_NEW_DRIVER_STATE ), m_cmdData.strMiCmd.c_str(), rErrMsg.c_str() ) ); - return MIstatus::failure; - } - return MIstatus::success; + if (!CMIDriver::Instance().SetDriverStateRunningDebugging()) + { + const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE), m_cmdData.strMiCmd.c_str(), rErrMsg.c_str())); + return MIstatus::failure; + } + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecRun::Acknowledge( void ) +bool +CMICmdCmdExecRun::Acknowledge(void) { - if( m_lldbResult.GetErrorSize() > 0 ) + if (m_lldbResult.GetErrorSize() > 0) { - const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() ); - const CMICmnMIValueResult miValueResult( "message", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); m_miResultRecord = miRecordResult; } else { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running ); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); m_miResultRecord = miRecordResult; - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID(); - // Give the client '=thread-group-started,id="i1" pid="xyz"' - m_bHasResultRecordExtra = true; - const CMICmnMIValueConst miValueConst2( "i1" ); - const CMICmnMIValueResult miValueResult2( "id", miValueConst2 ); - const CMIUtilString strPid( CMIUtilString::Format( "%lld", pid ) ); - const CMICmnMIValueConst miValueConst( strPid ); - const CMICmnMIValueResult miValueResult( "pid", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2 ); - miOutOfBand.Add( miValueResult ); - m_miResultRecordExtra = miOutOfBand.GetString(); + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID(); + // Give the client '=thread-group-started,id="i1" pid="xyz"' + m_bHasResultRecordExtra = true; + const CMICmnMIValueConst miValueConst2("i1"); + const CMICmnMIValueResult miValueResult2("id", miValueConst2); + const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); + const CMICmnMIValueConst miValueConst(strPid); + const CMICmnMIValueResult miValueResult("pid", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2); + miOutOfBand.Add(miValueResult); + m_miResultRecordExtra = miOutOfBand.GetString(); } - - return MIstatus::success; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdExecRun::CreateSelf( void ) +CMICmdBase * +CMICmdCmdExecRun::CreateSelf(void) { - return new CMICmdCmdExecRun(); + return new CMICmdCmdExecRun(); } //--------------------------------------------------------------------------------------- @@ -170,111 +172,114 @@ CMICmdBase * CMICmdCmdExecRun::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecContinue constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecContinue constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecContinue::CMICmdCmdExecContinue( void ) +CMICmdCmdExecContinue::CMICmdCmdExecContinue(void) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-continue"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecContinue::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-continue"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecContinue::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecContinue destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecContinue destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecContinue::~CMICmdCmdExecContinue( void ) +CMICmdCmdExecContinue::~CMICmdCmdExecContinue(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecContinue::Execute( void ) +bool +CMICmdCmdExecContinue::Execute(void) { - const MIchar * pCmd = "continue"; - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - const lldb::ReturnStatus rtn = rSessionInfo.m_rLldbDebugger.GetCommandInterpreter().HandleCommand( pCmd, m_lldbResult ); MIunused( rtn ); - + const MIchar *pCmd = "continue"; + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + const lldb::ReturnStatus rtn = rSessionInfo.m_rLldbDebugger.GetCommandInterpreter().HandleCommand(pCmd, m_lldbResult); + MIunused(rtn); - if( m_lldbResult.GetErrorSize() == 0 ) - { - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - if( !CMIDriver::Instance().SetDriverStateRunningDebugging() ) - { - const CMIUtilString & rErrMsg( CMIDriver::Instance().GetErrorDescription() ); - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_SET_NEW_DRIVER_STATE ), m_cmdData.strMiCmd.c_str(), rErrMsg.c_str() ) ); - return MIstatus::failure; - } - } - else - { - // ToDo: Re-evaluate if this is required when application near finished as this is parsing LLDB error message - // which seems a hack and is code brittle - const MIchar * pLldbErr = m_lldbResult.GetError(); - const CMIUtilString strLldbMsg( CMIUtilString( pLldbErr ).StripCREndOfLine() ); - if( strLldbMsg == "error: Process must be launched." ) - { - CMIDriver::Instance().SetExitApplicationFlag( true ); - } - } + if (m_lldbResult.GetErrorSize() == 0) + { + // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM + if (!CMIDriver::Instance().SetDriverStateRunningDebugging()) + { + const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE), m_cmdData.strMiCmd.c_str(), rErrMsg.c_str())); + return MIstatus::failure; + } + } + else + { + // ToDo: Re-evaluate if this is required when application near finished as this is parsing LLDB error message + // which seems a hack and is code brittle + const MIchar *pLldbErr = m_lldbResult.GetError(); + const CMIUtilString strLldbMsg(CMIUtilString(pLldbErr).StripCREndOfLine()); + if (strLldbMsg == "error: Process must be launched.") + { + CMIDriver::Instance().SetExitApplicationFlag(true); + } + } - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecContinue::Acknowledge( void ) +bool +CMICmdCmdExecContinue::Acknowledge(void) { - if( m_lldbResult.GetErrorSize() > 0 ) - { - const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() ); - const CMICmnMIValueResult miValueResult( "message", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - } - else - { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running ); - m_miResultRecord = miRecordResult; - } - - return MIstatus::success; + if (m_lldbResult.GetErrorSize() > 0) + { + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + } + else + { + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); + m_miResultRecord = miRecordResult; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdExecContinue::CreateSelf( void ) +CMICmdBase * +CMICmdCmdExecContinue::CreateSelf(void) { - return new CMICmdCmdExecContinue(); + return new CMICmdCmdExecContinue(); } //--------------------------------------------------------------------------------------- @@ -282,120 +287,126 @@ CMICmdBase * CMICmdCmdExecContinue::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecNext constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecNext constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecNext::CMICmdCmdExecNext( void ) -: m_constStrArgThread( "thread" ) -, m_constStrArgNumber( "number" ) +CMICmdCmdExecNext::CMICmdCmdExecNext(void) + : m_constStrArgThread("thread") + , m_constStrArgNumber("number") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-next"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecNext::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-next"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecNext::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecNext destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecNext destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecNext::~CMICmdCmdExecNext( void ) +CMICmdCmdExecNext::~CMICmdCmdExecNext(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecNext::ParseArgs( void ) +bool +CMICmdCmdExecNext::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNumber, false, false ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumber, false, false))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecNext::Execute( void ) +bool +CMICmdCmdExecNext::Execute(void) { - CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread ); + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_THREAD_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) ); - return MIstatus::failure; - } + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (!pArgThread->GetExpectedOption(nThreadId)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); + return MIstatus::failure; + } - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBDebugger & rDebugger = rSessionInfo.m_rLldbDebugger; - CMIUtilString strCmd( "thread step-over" ); - if( nThreadId != UINT64_MAX ) - strCmd += CMIUtilString::Format( " %llu", nThreadId ); - rDebugger.GetCommandInterpreter().HandleCommand( strCmd.c_str(), m_lldbResult, false ); + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBDebugger &rDebugger = rSessionInfo.m_rLldbDebugger; + CMIUtilString strCmd("thread step-over"); + if (nThreadId != UINT64_MAX) + strCmd += CMIUtilString::Format(" %llu", nThreadId); + rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecNext::Acknowledge( void ) +bool +CMICmdCmdExecNext::Acknowledge(void) { - if( m_lldbResult.GetErrorSize() > 0 ) - { - const MIchar * pLldbErr = m_lldbResult.GetError(); MIunused( pLldbErr ); - const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() ); - const CMICmnMIValueResult miValueResult( "message", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - } - else - { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running ); - m_miResultRecord = miRecordResult; - } + if (m_lldbResult.GetErrorSize() > 0) + { + const MIchar *pLldbErr = m_lldbResult.GetError(); + MIunused(pLldbErr); + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + } + else + { + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); + m_miResultRecord = miRecordResult; + } - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdExecNext::CreateSelf( void ) +CMICmdBase * +CMICmdCmdExecNext::CreateSelf(void) { - return new CMICmdCmdExecNext(); + return new CMICmdCmdExecNext(); } //--------------------------------------------------------------------------------------- @@ -403,120 +414,126 @@ CMICmdBase * CMICmdCmdExecNext::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecStep constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecStep constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecStep::CMICmdCmdExecStep( void ) -: m_constStrArgThread( "thread" ) -, m_constStrArgNumber( "number" ) +CMICmdCmdExecStep::CMICmdCmdExecStep(void) + : m_constStrArgThread("thread") + , m_constStrArgNumber("number") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-step"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecStep::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-step"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecStep::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecStep destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecStep destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecStep::~CMICmdCmdExecStep( void ) +CMICmdCmdExecStep::~CMICmdCmdExecStep(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecStep::ParseArgs( void ) +bool +CMICmdCmdExecStep::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNumber, false, false ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumber, false, false))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecStep::Execute( void ) +bool +CMICmdCmdExecStep::Execute(void) { - CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread ); + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) ); - return MIstatus::failure; - } + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (!pArgThread->GetExpectedOption(nThreadId)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); + return MIstatus::failure; + } - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBDebugger & rDebugger = rSessionInfo.m_rLldbDebugger; - CMIUtilString strCmd( "thread step-in" ); - if( nThreadId != UINT64_MAX ) - strCmd += CMIUtilString::Format( " %llu", nThreadId ); - rDebugger.GetCommandInterpreter().HandleCommand( strCmd.c_str(), m_lldbResult, false ); + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBDebugger &rDebugger = rSessionInfo.m_rLldbDebugger; + CMIUtilString strCmd("thread step-in"); + if (nThreadId != UINT64_MAX) + strCmd += CMIUtilString::Format(" %llu", nThreadId); + rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecStep::Acknowledge( void ) +bool +CMICmdCmdExecStep::Acknowledge(void) { - if( m_lldbResult.GetErrorSize() > 0 ) - { - const MIchar * pLldbErr = m_lldbResult.GetError(); MIunused( pLldbErr ); - const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() ); - const CMICmnMIValueResult miValueResult( "message", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - } - else - { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running ); - m_miResultRecord = miRecordResult; - } + if (m_lldbResult.GetErrorSize() > 0) + { + const MIchar *pLldbErr = m_lldbResult.GetError(); + MIunused(pLldbErr); + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + } + else + { + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); + m_miResultRecord = miRecordResult; + } - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdExecStep::CreateSelf( void ) +CMICmdBase * +CMICmdCmdExecStep::CreateSelf(void) { - return new CMICmdCmdExecStep(); + return new CMICmdCmdExecStep(); } //--------------------------------------------------------------------------------------- @@ -524,120 +541,126 @@ CMICmdBase * CMICmdCmdExecStep::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecNextInstruction constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecNextInstruction constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecNextInstruction::CMICmdCmdExecNextInstruction( void ) -: m_constStrArgThread( "thread" ) -, m_constStrArgNumber( "number" ) +CMICmdCmdExecNextInstruction::CMICmdCmdExecNextInstruction(void) + : m_constStrArgThread("thread") + , m_constStrArgNumber("number") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-next-instruction"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecNextInstruction::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-next-instruction"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecNextInstruction::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecNextInstruction destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecNextInstruction destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecNextInstruction::~CMICmdCmdExecNextInstruction( void ) +CMICmdCmdExecNextInstruction::~CMICmdCmdExecNextInstruction(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecNextInstruction::ParseArgs( void ) +bool +CMICmdCmdExecNextInstruction::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNumber, false, false ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumber, false, false))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecNextInstruction::Execute( void ) +bool +CMICmdCmdExecNextInstruction::Execute(void) { - CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread ); + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) ); - return MIstatus::failure; - } + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (!pArgThread->GetExpectedOption(nThreadId)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); + return MIstatus::failure; + } - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBDebugger & rDebugger = rSessionInfo.m_rLldbDebugger; - CMIUtilString strCmd( "thread step-inst-over" ); - if( nThreadId != UINT64_MAX ) - strCmd += CMIUtilString::Format( " %llu", nThreadId ); - rDebugger.GetCommandInterpreter().HandleCommand( strCmd.c_str(), m_lldbResult, false ); + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBDebugger &rDebugger = rSessionInfo.m_rLldbDebugger; + CMIUtilString strCmd("thread step-inst-over"); + if (nThreadId != UINT64_MAX) + strCmd += CMIUtilString::Format(" %llu", nThreadId); + rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecNextInstruction::Acknowledge( void ) +bool +CMICmdCmdExecNextInstruction::Acknowledge(void) { - if( m_lldbResult.GetErrorSize() > 0 ) - { - const MIchar * pLldbErr = m_lldbResult.GetError(); MIunused( pLldbErr ); - const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() ); - const CMICmnMIValueResult miValueResult( "message", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - } - else - { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running ); - m_miResultRecord = miRecordResult; - } + if (m_lldbResult.GetErrorSize() > 0) + { + const MIchar *pLldbErr = m_lldbResult.GetError(); + MIunused(pLldbErr); + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + } + else + { + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); + m_miResultRecord = miRecordResult; + } - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdExecNextInstruction::CreateSelf( void ) +CMICmdBase * +CMICmdCmdExecNextInstruction::CreateSelf(void) { - return new CMICmdCmdExecNextInstruction(); + return new CMICmdCmdExecNextInstruction(); } //--------------------------------------------------------------------------------------- @@ -645,120 +668,126 @@ CMICmdBase * CMICmdCmdExecNextInstruction::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecStepInstruction constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecStepInstruction constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecStepInstruction::CMICmdCmdExecStepInstruction( void ) -: m_constStrArgThread( "thread" ) -, m_constStrArgNumber( "number" ) +CMICmdCmdExecStepInstruction::CMICmdCmdExecStepInstruction(void) + : m_constStrArgThread("thread") + , m_constStrArgNumber("number") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-step-instruction"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecStepInstruction::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-step-instruction"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecStepInstruction::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecStepInstruction destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecStepInstruction destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecStepInstruction::~CMICmdCmdExecStepInstruction( void ) +CMICmdCmdExecStepInstruction::~CMICmdCmdExecStepInstruction(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecStepInstruction::ParseArgs( void ) +bool +CMICmdCmdExecStepInstruction::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNumber, false, false ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumber, false, false))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecStepInstruction::Execute( void ) +bool +CMICmdCmdExecStepInstruction::Execute(void) { - CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread ); + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) ); - return MIstatus::failure; - } + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (!pArgThread->GetExpectedOption(nThreadId)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); + return MIstatus::failure; + } - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBDebugger & rDebugger = rSessionInfo.m_rLldbDebugger; - CMIUtilString strCmd( "thread step-inst" ); - if( nThreadId != UINT64_MAX ) - strCmd += CMIUtilString::Format( " %llu", nThreadId ); - rDebugger.GetCommandInterpreter().HandleCommand( strCmd.c_str(), m_lldbResult, false ); + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBDebugger &rDebugger = rSessionInfo.m_rLldbDebugger; + CMIUtilString strCmd("thread step-inst"); + if (nThreadId != UINT64_MAX) + strCmd += CMIUtilString::Format(" %llu", nThreadId); + rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecStepInstruction::Acknowledge( void ) +bool +CMICmdCmdExecStepInstruction::Acknowledge(void) { - if( m_lldbResult.GetErrorSize() > 0 ) - { - const MIchar * pLldbErr = m_lldbResult.GetError(); MIunused( pLldbErr ); - const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() ); - const CMICmnMIValueResult miValueResult( "message", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - } - else - { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running ); - m_miResultRecord = miRecordResult; - } + if (m_lldbResult.GetErrorSize() > 0) + { + const MIchar *pLldbErr = m_lldbResult.GetError(); + MIunused(pLldbErr); + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + } + else + { + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); + m_miResultRecord = miRecordResult; + } - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdExecStepInstruction::CreateSelf( void ) +CMICmdBase * +CMICmdCmdExecStepInstruction::CreateSelf(void) { - return new CMICmdCmdExecStepInstruction(); + return new CMICmdCmdExecStepInstruction(); } //--------------------------------------------------------------------------------------- @@ -766,120 +795,127 @@ CMICmdBase * CMICmdCmdExecStepInstruction::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecFinish constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecFinish constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecFinish::CMICmdCmdExecFinish( void ) -: m_constStrArgThread( "thread" ) -, m_constStrArgFrame( "frame" ) +CMICmdCmdExecFinish::CMICmdCmdExecFinish(void) + : m_constStrArgThread("thread") + , m_constStrArgFrame("frame") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-finish"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecFinish::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-finish"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecFinish::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecFinish destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecFinish destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecFinish::~CMICmdCmdExecFinish( void ) +CMICmdCmdExecFinish::~CMICmdCmdExecFinish(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecFinish::ParseArgs( void ) +bool +CMICmdCmdExecFinish::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgFrame, false, false, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgFrame, false, false, CMICmdArgValListBase::eArgValType_Number, 1))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecFinish::Execute( void ) +bool +CMICmdCmdExecFinish::Execute(void) { - CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread ); + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (!pArgThread->GetExpectedOption(nThreadId)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); + return MIstatus::failure; + } - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) ); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBDebugger & rDebugger = rSessionInfo.m_rLldbDebugger; - CMIUtilString strCmd( "thread step-out" ); - if( nThreadId != UINT64_MAX ) - strCmd += CMIUtilString::Format( " %llu", nThreadId ); - rDebugger.GetCommandInterpreter().HandleCommand( strCmd.c_str(), m_lldbResult, false ); + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBDebugger &rDebugger = rSessionInfo.m_rLldbDebugger; + CMIUtilString strCmd("thread step-out"); + if (nThreadId != UINT64_MAX) + strCmd += CMIUtilString::Format(" %llu", nThreadId); + rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecFinish::Acknowledge( void ) +bool +CMICmdCmdExecFinish::Acknowledge(void) { - if( m_lldbResult.GetErrorSize() > 0 ) - { - const MIchar * pLldbErr = m_lldbResult.GetError(); MIunused( pLldbErr ); - const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() ); - const CMICmnMIValueResult miValueResult( "message", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - } - else - { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running ); - m_miResultRecord = miRecordResult; - } + if (m_lldbResult.GetErrorSize() > 0) + { + const MIchar *pLldbErr = m_lldbResult.GetError(); + MIunused(pLldbErr); + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + } + else + { + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); + m_miResultRecord = miRecordResult; + } - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdExecFinish::CreateSelf( void ) +CMICmdBase * +CMICmdCmdExecFinish::CreateSelf(void) { - return new CMICmdCmdExecFinish(); + return new CMICmdCmdExecFinish(); } //--------------------------------------------------------------------------------------- @@ -887,96 +923,99 @@ CMICmdBase * CMICmdCmdExecFinish::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecInterrupt constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecInterrupt constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecInterrupt::CMICmdCmdExecInterrupt( void ) +CMICmdCmdExecInterrupt::CMICmdCmdExecInterrupt(void) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-interrupt"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecInterrupt::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-interrupt"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecInterrupt::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdExecInterrupt destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdExecInterrupt destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdExecInterrupt::~CMICmdCmdExecInterrupt( void ) +CMICmdCmdExecInterrupt::~CMICmdCmdExecInterrupt(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecInterrupt::Execute( void ) +bool +CMICmdCmdExecInterrupt::Execute(void) { - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBDebugger & rDebugger = rSessionInfo.m_rLldbDebugger; - CMIUtilString strCmd( "process interrupt" ); - const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand( strCmd.c_str(), m_lldbResult, false ); MIunused( status ); + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBDebugger &rDebugger = rSessionInfo.m_rLldbDebugger; + CMIUtilString strCmd("process interrupt"); + const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); + MIunused(status); - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - if( !CMIDriver::Instance().SetDriverStateRunningNotDebugging() ) - { - const CMIUtilString & rErrMsg( CMIDriver::Instance().GetErrorDescription() ); - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_SET_NEW_DRIVER_STATE ), strCmd.c_str(), rErrMsg.c_str() ) ); - return MIstatus::failure; - } + // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM + if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging()) + { + const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE), strCmd.c_str(), rErrMsg.c_str())); + return MIstatus::failure; + } - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdExecInterrupt::Acknowledge( void ) +bool +CMICmdCmdExecInterrupt::Acknowledge(void) { - if( m_lldbResult.GetErrorSize() > 0 ) + if (m_lldbResult.GetErrorSize() > 0) { - const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() ); - const CMICmnMIValueResult miValueResult( "message", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); m_miResultRecord = miRecordResult; } else { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done ); - m_miResultRecord = miRecordResult; - } - - return MIstatus::success; + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdExecInterrupt::CreateSelf( void ) +CMICmdBase * +CMICmdCmdExecInterrupt::CreateSelf(void) { - return new CMICmdCmdExecInterrupt(); + return new CMICmdCmdExecInterrupt(); } - diff --git a/tools/lldb-mi/MICmdCmdExec.h b/tools/lldb-mi/MICmdCmdExec.h index a712b23ca5e0..cf59ec4f5b3e 100644 --- a/tools/lldb-mi/MICmdCmdExec.h +++ b/tools/lldb-mi/MICmdCmdExec.h @@ -8,31 +8,31 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdExec.h +// File: MICmdCmdExec.h // -// Overview: CMICmdCmdExecRun interface. -// CMICmdCmdExecContinue interface. -// CMICmdCmdExecNext interface. -// CMICmdCmdExecStep interface. -// CMICmdCmdExecNextInstruction interface. -// CMICmdCmdExecStepInstruction interface. -// CMICmdCmdExecFinish interface. -// CMICmdCmdExecInterrupt interface. +// Overview: CMICmdCmdExecRun interface. +// CMICmdCmdExecContinue interface. +// CMICmdCmdExecNext interface. +// CMICmdCmdExecStep interface. +// CMICmdCmdExecNextInstruction interface. +// CMICmdCmdExecStepInstruction interface. +// CMICmdCmdExecFinish interface. +// CMICmdCmdExecInterrupt interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -44,267 +44,266 @@ #include "MICmdBase.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "exec-run". -// Gotchas: None. -// Authors: Illya Rudkin 07/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "exec-run". +// Gotchas: None. +// Authors: Illya Rudkin 07/03/2014. +// Changes: None. //-- class CMICmdCmdExecRun : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdExecRun( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdExecRun( void ); - -// Attributes: -private: - lldb::SBCommandReturnObject m_lldbResult; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdExecRun(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdExecRun(void); + + // Attributes: + private: + lldb::SBCommandReturnObject m_lldbResult; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "exec-continue". -// Gotchas: None. -// Authors: Illya Rudkin 07/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "exec-continue". +// Gotchas: None. +// Authors: Illya Rudkin 07/03/2014. +// Changes: None. //-- class CMICmdCmdExecContinue : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdExecContinue( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdExecContinue( void ); - -// Attributes: -private: - lldb::SBCommandReturnObject m_lldbResult; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdExecContinue(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdExecContinue(void); + + // Attributes: + private: + lldb::SBCommandReturnObject m_lldbResult; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "exec-next". -// Gotchas: None. -// Authors: Illya Rudkin 25/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "exec-next". +// Gotchas: None. +// Authors: Illya Rudkin 25/03/2014. +// Changes: None. //-- class CMICmdCmdExecNext : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdExecNext( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdExecNext( void ); - -// Attributes: -private: - lldb::SBCommandReturnObject m_lldbResult; - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdExecNext(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdExecNext(void); + + // Attributes: + private: + lldb::SBCommandReturnObject m_lldbResult; + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "exec-step". -// Gotchas: None. -// Authors: Illya Rudkin 25/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "exec-step". +// Gotchas: None. +// Authors: Illya Rudkin 25/03/2014. +// Changes: None. //-- class CMICmdCmdExecStep : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdExecStep( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdExecStep( void ); - -// Attributes: -private: - lldb::SBCommandReturnObject m_lldbResult; - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdExecStep(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdExecStep(void); + + // Attributes: + private: + lldb::SBCommandReturnObject m_lldbResult; + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "exec-next-instruction". -// Gotchas: None. -// Authors: Illya Rudkin 25/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "exec-next-instruction". +// Gotchas: None. +// Authors: Illya Rudkin 25/03/2014. +// Changes: None. //-- class CMICmdCmdExecNextInstruction : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdExecNextInstruction( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdExecNextInstruction( void ); - -// Attributes: -private: - lldb::SBCommandReturnObject m_lldbResult; - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdExecNextInstruction(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdExecNextInstruction(void); + + // Attributes: + private: + lldb::SBCommandReturnObject m_lldbResult; + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "exec-step-instruction". -// Gotchas: None. -// Authors: Illya Rudkin 25/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "exec-step-instruction". +// Gotchas: None. +// Authors: Illya Rudkin 25/03/2014. +// Changes: None. //-- class CMICmdCmdExecStepInstruction : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdExecStepInstruction( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdExecStepInstruction( void ); - -// Attributes: -private: - lldb::SBCommandReturnObject m_lldbResult; - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdExecStepInstruction(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdExecStepInstruction(void); + + // Attributes: + private: + lldb::SBCommandReturnObject m_lldbResult; + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "exec-finish". -// Gotchas: None. -// Authors: Illya Rudkin 25/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "exec-finish". +// Gotchas: None. +// Authors: Illya Rudkin 25/03/2014. +// Changes: None. //-- class CMICmdCmdExecFinish : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdExecFinish( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdExecFinish( void ); - -// Attributes: -private: - lldb::SBCommandReturnObject m_lldbResult; - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdExecFinish(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdExecFinish(void); + + // Attributes: + private: + lldb::SBCommandReturnObject m_lldbResult; + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option }; // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "exec-interrupt". -// Gotchas: Using Eclipse this command is injected into the command system when a -// SIGINT signal is received while running an inferior program. -// Authors: Illya Rudkin 03/06/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "exec-interrupt". +// Gotchas: Using Eclipse this command is injected into the command system when a +// SIGINT signal is received while running an inferior program. +// Authors: Illya Rudkin 03/06/2014. +// Changes: None. //-- class CMICmdCmdExecInterrupt : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdExecInterrupt( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdExecInterrupt( void ); - -// Attributes: -private: - lldb::SBCommandReturnObject m_lldbResult; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdExecInterrupt(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdExecInterrupt(void); + + // Attributes: + private: + lldb::SBCommandReturnObject m_lldbResult; }; - diff --git a/tools/lldb-mi/MICmdCmdFile.cpp b/tools/lldb-mi/MICmdCmdFile.cpp index 1d0b494362ce..a954f88dac11 100644 --- a/tools/lldb-mi/MICmdCmdFile.cpp +++ b/tools/lldb-mi/MICmdCmdFile.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdFile.cpp +// File: MICmdCmdFile.cpp // -// Overview: CMICmdCmdFileExecAndSymbols implementation. +// Overview: CMICmdCmdFileExecAndSymbols implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third Party Headers: @@ -32,153 +32,161 @@ #include "MICmdArgValOptionLong.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdFileExecAndSymbols constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdFileExecAndSymbols constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdFileExecAndSymbols::CMICmdCmdFileExecAndSymbols( void ) -: m_constStrArgNameFile( "file" ) -, m_constStrArgThreadGrp( "thread-group" ) +CMICmdCmdFileExecAndSymbols::CMICmdCmdFileExecAndSymbols(void) + : m_constStrArgNameFile("file") + , m_constStrArgThreadGrp("thread-group") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "file-exec-and-symbols"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdFileExecAndSymbols::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "file-exec-and-symbols"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdFileExecAndSymbols::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdFileExecAndSymbols destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdFileExecAndSymbols destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdFileExecAndSymbols::~CMICmdCmdFileExecAndSymbols( void ) +CMICmdCmdFileExecAndSymbols::~CMICmdCmdFileExecAndSymbols(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdFileExecAndSymbols::ParseArgs( void ) +bool +CMICmdCmdFileExecAndSymbols::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValFile( m_constStrArgNameFile, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add( + *(new CMICmdArgValOptionLong(m_constStrArgThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValFile(m_constStrArgNameFile, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Synopsis: -file-exec-and-symbols file -// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-File-Commands.html#GDB_002fMI-File-Commands -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Synopsis: -file-exec-and-symbols file +// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-File-Commands.html#GDB_002fMI-File-Commands +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdFileExecAndSymbols::Execute( void ) +bool +CMICmdCmdFileExecAndSymbols::Execute(void) { - CMICMDBASE_GETOPTION( pArgNamedFile, File, m_constStrArgNameFile ); - CMICmdArgValFile * pArgFile = static_cast< CMICmdArgValFile * >( pArgNamedFile ); - const CMIUtilString & strExeFilePath( pArgFile->GetValue() ); - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBDebugger & rDbgr = rSessionInfo.m_rLldbDebugger; - lldb::SBError error; - const MIchar * pTargetTriple = nullptr; // Let LLDB discover the triple required - const MIchar * pTargetPlatformName = ""; - const bool bAddDepModules = false; - lldb::SBTarget target = rDbgr.CreateTarget( strExeFilePath.c_str(), pTargetTriple, pTargetPlatformName, bAddDepModules, error ); - CMIUtilString strWkDir; - const CMIUtilString & rStrKeyWkDir( rSessionInfo.m_constStrSharedDataKeyWkDir ); - if( !rSessionInfo.SharedDataRetrieve< CMIUtilString >( rStrKeyWkDir, strWkDir ) ) - { - strWkDir = CMIUtilFileStd().StripOffFileName( strExeFilePath ); - if( !rSessionInfo.SharedDataAdd< CMIUtilString >( rStrKeyWkDir, strWkDir ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_DBGSESSION_ERR_SHARED_DATA_ADD ), m_cmdData.strMiCmd.c_str(), rStrKeyWkDir.c_str() ) ); - return MIstatus::failure; - } - } - if( !rDbgr.SetCurrentPlatformSDKRoot( strWkDir.c_str() ) ) - { + CMICMDBASE_GETOPTION(pArgNamedFile, File, m_constStrArgNameFile); + CMICmdArgValFile *pArgFile = static_cast(pArgNamedFile); + const CMIUtilString &strExeFilePath(pArgFile->GetValue()); + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBDebugger &rDbgr = rSessionInfo.m_rLldbDebugger; + lldb::SBError error; + const MIchar *pTargetTriple = nullptr; // Let LLDB discover the triple required + const MIchar *pTargetPlatformName = ""; + const bool bAddDepModules = false; + lldb::SBTarget target = rDbgr.CreateTarget(strExeFilePath.c_str(), pTargetTriple, pTargetPlatformName, bAddDepModules, error); + CMIUtilString strWkDir; + const CMIUtilString &rStrKeyWkDir(rSessionInfo.m_constStrSharedDataKeyWkDir); + if (!rSessionInfo.SharedDataRetrieve(rStrKeyWkDir, strWkDir)) + { + strWkDir = CMIUtilFileStd().StripOffFileName(strExeFilePath); + if (!rSessionInfo.SharedDataAdd(rStrKeyWkDir, strWkDir)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), m_cmdData.strMiCmd.c_str(), rStrKeyWkDir.c_str())); + return MIstatus::failure; + } + } + if (!rDbgr.SetCurrentPlatformSDKRoot(strWkDir.c_str())) + { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_FNFAILED ), m_cmdData.strMiCmd.c_str(), "SetCurrentPlatformSDKRoot()" ) ); - return MIstatus::failure; - } - lldb::SBStream err; - if( error.Fail() ) - { - const bool bOk = error.GetDescription( err ); MIunused( bOk ); - } - if( !target.IsValid() ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_TARGET ), m_cmdData.strMiCmd.c_str(), strExeFilePath.c_str(), err.GetData() ) ); - return MIstatus::failure; - } - if( error.Fail() ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_CREATE_TARGET ), m_cmdData.strMiCmd.c_str(), err.GetData() ) ); - return MIstatus::failure; - } + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), m_cmdData.strMiCmd.c_str(), "SetCurrentPlatformSDKRoot()")); + return MIstatus::failure; + } + lldb::SBStream err; + if (error.Fail()) + { + const bool bOk = error.GetDescription(err); + MIunused(bOk); + } + if (!target.IsValid()) + { + SetError( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET), m_cmdData.strMiCmd.c_str(), strExeFilePath.c_str(), err.GetData())); + return MIstatus::failure; + } + if (error.Fail()) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_CREATE_TARGET), m_cmdData.strMiCmd.c_str(), err.GetData())); + return MIstatus::failure; + } - rSessionInfo.m_lldbTarget = target; + rSessionInfo.m_lldbTarget = target; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdFileExecAndSymbols::Acknowledge( void ) +bool +CMICmdCmdFileExecAndSymbols::Acknowledge(void) { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done ); - m_miResultRecord = miRecordResult; + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdFileExecAndSymbols::CreateSelf( void ) +CMICmdBase * +CMICmdCmdFileExecAndSymbols::CreateSelf(void) { - return new CMICmdCmdFileExecAndSymbols(); + return new CMICmdCmdFileExecAndSymbols(); } //++ ------------------------------------------------------------------------------------ -// Details: If the MI Driver is not operating via a client i.e. Eclipse but say operating -// on a executable passed in as a argument to the drive then what should the driver -// do on a command failing? Either continue operating or exit the application. -// Override this function where a command failure cannot allow the driver to -// continue operating. -// Type: Overridden. -// Args: None. -// Return: bool - True = Fatal if command fails, false = can continue if command fails. -// Throws: None. +// Details: If the MI Driver is not operating via a client i.e. Eclipse but say operating +// on a executable passed in as a argument to the drive then what should the driver +// do on a command failing? Either continue operating or exit the application. +// Override this function where a command failure cannot allow the driver to +// continue operating. +// Type: Overridden. +// Args: None. +// Return: bool - True = Fatal if command fails, false = can continue if command fails. +// Throws: None. //-- -bool CMICmdCmdFileExecAndSymbols::GetExitAppOnCommandFailure( void ) const +bool +CMICmdCmdFileExecAndSymbols::GetExitAppOnCommandFailure(void) const { - return true; -} \ No newline at end of file + return true; +} diff --git a/tools/lldb-mi/MICmdCmdFile.h b/tools/lldb-mi/MICmdCmdFile.h index a80a313ea7b5..5e23c85daeff 100644 --- a/tools/lldb-mi/MICmdCmdFile.h +++ b/tools/lldb-mi/MICmdCmdFile.h @@ -8,24 +8,24 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdFile.h +// File: MICmdCmdFile.h // -// Overview: CMICmdCmdFileExecAndSymbols interface. +// Overview: CMICmdCmdFileExecAndSymbols interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -36,36 +36,37 @@ #include "MICmnMIValueList.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "file-exec-and-symbols". -// This command does not follow the MI documentation exactly. -// Gotchas: None. -// Authors: Illya Rudkin 25/02/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "file-exec-and-symbols". +// This command does not follow the MI documentation exactly. +// Gotchas: None. +// Authors: Illya Rudkin 25/02/2014. +// Changes: None. //-- class CMICmdCmdFileExecAndSymbols : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdFileExecAndSymbols( void ); + // Methods: + public: + /* ctor */ CMICmdCmdFileExecAndSymbols(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdFileExecAndSymbols( void ); - virtual bool GetExitAppOnCommandFailure( void ) const; + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdFileExecAndSymbols(void); + virtual bool GetExitAppOnCommandFailure(void) const; -// Attributes: -private: - const CMIUtilString m_constStrArgNameFile; - const CMIUtilString m_constStrArgThreadGrp; // Not handled by *this command. Not specified in MI spec but Eclipse gives this option sometimes + // Attributes: + private: + const CMIUtilString m_constStrArgNameFile; + const CMIUtilString + m_constStrArgThreadGrp; // Not handled by *this command. Not specified in MI spec but Eclipse gives this option sometimes }; diff --git a/tools/lldb-mi/MICmdCmdGdbInfo.cpp b/tools/lldb-mi/MICmdCmdGdbInfo.cpp index 62bb1f280bc3..dde6a0b40135 100644 --- a/tools/lldb-mi/MICmdCmdGdbInfo.cpp +++ b/tools/lldb-mi/MICmdCmdGdbInfo.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdGdbInfo.cpp +// File: MICmdCmdGdbInfo.cpp // -// Overview: CMICmdCmdGdbInfo implementation. +// Overview: CMICmdCmdGdbInfo implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third party headers: @@ -31,202 +31,208 @@ #include "MICmnLLDBDebugSessionInfo.h" // Instantiations: -const CMICmdCmdGdbInfo::MapPrintFnNameToPrintFn_t CMICmdCmdGdbInfo::ms_mapPrintFnNameToPrintFn = -{ - { "sharedlibrary", &CMICmdCmdGdbInfo::PrintFnSharedLibrary } -}; +const CMICmdCmdGdbInfo::MapPrintFnNameToPrintFn_t CMICmdCmdGdbInfo::ms_mapPrintFnNameToPrintFn = { + {"sharedlibrary", &CMICmdCmdGdbInfo::PrintFnSharedLibrary}}; //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdGdbInfo constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdGdbInfo constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdGdbInfo::CMICmdCmdGdbInfo( void ) -: m_constStrArgNamedPrint( "print" ) -, m_bPrintFnRecognised( true ) -, m_bPrintFnSuccessful( false ) -, m_strPrintFnError( MIRSRC( IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS ) ) +CMICmdCmdGdbInfo::CMICmdCmdGdbInfo(void) + : m_constStrArgNamedPrint("print") + , m_bPrintFnRecognised(true) + , m_bPrintFnSuccessful(false) + , m_strPrintFnError(MIRSRC(IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS)) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "info"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdGdbInfo::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "info"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdGdbInfo::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdGdbInfo destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdGdbInfo destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdGdbInfo::~CMICmdCmdGdbInfo( void ) +CMICmdCmdGdbInfo::~CMICmdCmdGdbInfo(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdGdbInfo::ParseArgs( void ) +bool +CMICmdCmdGdbInfo::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedPrint, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedPrint, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdGdbInfo::Execute( void ) +bool +CMICmdCmdGdbInfo::Execute(void) { - CMICMDBASE_GETOPTION( pArgPrint, String, m_constStrArgNamedPrint ); - const CMIUtilString & rPrintRequest( pArgPrint->GetValue() ); - - FnPrintPtr pPrintRequestFn = nullptr; - if( !GetPrintFn( rPrintRequest, pPrintRequestFn ) ) - { - m_strPrintFnName = rPrintRequest; - m_bPrintFnRecognised = false; - return MIstatus::success; - } - - m_bPrintFnSuccessful = (this->*(pPrintRequestFn))(); - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgPrint, String, m_constStrArgNamedPrint); + const CMIUtilString &rPrintRequest(pArgPrint->GetValue()); + + FnPrintPtr pPrintRequestFn = nullptr; + if (!GetPrintFn(rPrintRequest, pPrintRequestFn)) + { + m_strPrintFnName = rPrintRequest; + m_bPrintFnRecognised = false; + return MIstatus::success; + } + + m_bPrintFnSuccessful = (this->*(pPrintRequestFn))(); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdGdbInfo::Acknowledge( void ) +bool +CMICmdCmdGdbInfo::Acknowledge(void) { - if( !m_bPrintFnRecognised ) - { - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND ), m_strPrintFnName.c_str() ) ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - if( m_bPrintFnSuccessful ) - { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INFO_PRINTFN_FAILED ), m_strPrintFnError.c_str() ) ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + if (!m_bPrintFnRecognised) + { + const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND), m_strPrintFnName.c_str())); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + if (m_bPrintFnSuccessful) + { + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_FAILED), m_strPrintFnError.c_str())); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdGdbInfo::CreateSelf( void ) +CMICmdBase * +CMICmdCmdGdbInfo::CreateSelf(void) { - return new CMICmdCmdGdbInfo(); + return new CMICmdCmdGdbInfo(); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the print function's pointer for the matching print request. -// Type: Method. -// Args: vrPrintFnName - (R) The info requested. -// vrwpFn - (W) The print function's pointer of the function to carry out -// Return: bool - True = Print request is implemented, false = not found. -// Throws: None. +// Details: Retrieve the print function's pointer for the matching print request. +// Type: Method. +// Args: vrPrintFnName - (R) The info requested. +// vrwpFn - (W) The print function's pointer of the function to carry out +// Return: bool - True = Print request is implemented, false = not found. +// Throws: None. //-- -bool CMICmdCmdGdbInfo::GetPrintFn( const CMIUtilString & vrPrintFnName, FnPrintPtr & vrwpFn ) const +bool +CMICmdCmdGdbInfo::GetPrintFn(const CMIUtilString &vrPrintFnName, FnPrintPtr &vrwpFn) const { - vrwpFn = nullptr; + vrwpFn = nullptr; - const MapPrintFnNameToPrintFn_t::const_iterator it = ms_mapPrintFnNameToPrintFn.find( vrPrintFnName ); - if( it != ms_mapPrintFnNameToPrintFn.end() ) - { - vrwpFn = (*it).second; - return true; - } + const MapPrintFnNameToPrintFn_t::const_iterator it = ms_mapPrintFnNameToPrintFn.find(vrPrintFnName); + if (it != ms_mapPrintFnNameToPrintFn.end()) + { + vrwpFn = (*it).second; + return true; + } - return false; + return false; } - + //++ ------------------------------------------------------------------------------------ -// Details: Carry out work to complete the request to prepare and send back information -// asked for. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Carry out work to complete the request to prepare and send back information +// asked for. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdGdbInfo::PrintFnSharedLibrary( void ) +bool +CMICmdCmdGdbInfo::PrintFnSharedLibrary(void) { - CMICmnStreamStdout & rStdout = CMICmnStreamStdout::Instance(); - bool bOk = rStdout.TextToStdout( "~\"From To Syms Read Shared Object Library\"" ); - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBTarget & rTarget = rSessionInfo.m_lldbTarget; - const MIuint nModules = rTarget.GetNumModules(); - for( MIuint i = 0; bOk && (i < nModules); i++ ) - { - lldb::SBModule module = rTarget.GetModuleAtIndex( i ); - if( module.IsValid() ) - { - const CMIUtilString strModuleFilePath( module.GetFileSpec().GetDirectory() ); - const CMIUtilString strModuleFileName( module.GetFileSpec().GetFilename() ); - const CMIUtilString strModuleFullPath( CMIUtilString::Format( "%s/%s", strModuleFilePath.c_str(), strModuleFileName.c_str() ) ); - const CMIUtilString strHasSymbols = (module.GetNumSymbols() > 0) ? "Yes" : "No"; - lldb::addr_t addrLoadS = 0xffffffff; - lldb::addr_t addrLoadSize = 0; - bool bHaveAddrLoad = false; - const MIuint nSections = module.GetNumSections(); - for( MIuint j = 0; j < nSections; j++ ) - { - lldb::SBSection section = module.GetSectionAtIndex( j ); - lldb::addr_t addrLoad = section.GetLoadAddress( rTarget ); - if( addrLoad != (lldb::addr_t) -1 ) - { - if( !bHaveAddrLoad ) - { - bHaveAddrLoad = true; - addrLoadS = addrLoad; - } - - addrLoadSize += section.GetByteSize(); - } - } - bOk = bOk && rStdout.TextToStdout( CMIUtilString::Format( "~\"0x%08x\t0x%08x\t%s\t\t%s\"", addrLoadS, addrLoadS + addrLoadSize, strHasSymbols.c_str(), strModuleFullPath.c_str() ) ); - } - } - - return bOk; + CMICmnStreamStdout &rStdout = CMICmnStreamStdout::Instance(); + bool bOk = rStdout.TextToStdout("~\"From To Syms Read Shared Object Library\""); + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBTarget &rTarget = rSessionInfo.m_lldbTarget; + const MIuint nModules = rTarget.GetNumModules(); + for (MIuint i = 0; bOk && (i < nModules); i++) + { + lldb::SBModule module = rTarget.GetModuleAtIndex(i); + if (module.IsValid()) + { + const CMIUtilString strModuleFilePath(module.GetFileSpec().GetDirectory()); + const CMIUtilString strModuleFileName(module.GetFileSpec().GetFilename()); + const CMIUtilString strModuleFullPath(CMIUtilString::Format("%s/%s", strModuleFilePath.c_str(), strModuleFileName.c_str())); + const CMIUtilString strHasSymbols = (module.GetNumSymbols() > 0) ? "Yes" : "No"; + lldb::addr_t addrLoadS = 0xffffffff; + lldb::addr_t addrLoadSize = 0; + bool bHaveAddrLoad = false; + const MIuint nSections = module.GetNumSections(); + for (MIuint j = 0; j < nSections; j++) + { + lldb::SBSection section = module.GetSectionAtIndex(j); + lldb::addr_t addrLoad = section.GetLoadAddress(rTarget); + if (addrLoad != (lldb::addr_t) - 1) + { + if (!bHaveAddrLoad) + { + bHaveAddrLoad = true; + addrLoadS = addrLoad; + } + + addrLoadSize += section.GetByteSize(); + } + } + bOk = bOk && + rStdout.TextToStdout(CMIUtilString::Format("~\"0x%08x\t0x%08x\t%s\t\t%s\"", addrLoadS, addrLoadS + addrLoadSize, + strHasSymbols.c_str(), strModuleFullPath.c_str())); + } + } + + return bOk; } diff --git a/tools/lldb-mi/MICmdCmdGdbInfo.h b/tools/lldb-mi/MICmdCmdGdbInfo.h index 3fa920669416..0d45e6c39335 100644 --- a/tools/lldb-mi/MICmdCmdGdbInfo.h +++ b/tools/lldb-mi/MICmdCmdGdbInfo.h @@ -8,24 +8,24 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdGdbInfo.h +// File: MICmdCmdGdbInfo.h // -// Overview: CMICmdCmdGdbInfo interface. +// Overview: CMICmdCmdGdbInfo interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -37,57 +37,57 @@ #include "MICmdBase.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements GDB command "info". -// The design of matching the info request to a request action (or -// command) is very simple. The request function which carries out -// the task of information gathering and printing to stdout is part of -// *this class. Should the request function become more complicated then -// that request should really reside in a command type class. Then this -// class instantiates a request info command for a matching request. The -// design/code of *this class then does not then become bloated. Use a -// lightweight version of the current MI command system. -// Gotchas: None. -// Authors: Illya Rudkin 05/06/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements GDB command "info". +// The design of matching the info request to a request action (or +// command) is very simple. The request function which carries out +// the task of information gathering and printing to stdout is part of +// *this class. Should the request function become more complicated then +// that request should really reside in a command type class. Then this +// class instantiates a request info command for a matching request. The +// design/code of *this class then does not then become bloated. Use a +// lightweight version of the current MI command system. +// Gotchas: None. +// Authors: Illya Rudkin 05/06/2014. +// Changes: None. //-- class CMICmdCmdGdbInfo : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdGdbInfo( void ); + // Methods: + public: + /* ctor */ CMICmdCmdGdbInfo(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdGdbInfo( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdGdbInfo(void); -// Typedefs: -private: - typedef bool (CMICmdCmdGdbInfo::*FnPrintPtr)(); - typedef std::map< CMIUtilString, FnPrintPtr > MapPrintFnNameToPrintFn_t; + // Typedefs: + private: + typedef bool (CMICmdCmdGdbInfo::*FnPrintPtr)(); + typedef std::map MapPrintFnNameToPrintFn_t; -// Methods: -private: - bool GetPrintFn( const CMIUtilString & vrPrintFnName, FnPrintPtr & vrwpFn ) const; - bool PrintFnSharedLibrary( void ); + // Methods: + private: + bool GetPrintFn(const CMIUtilString &vrPrintFnName, FnPrintPtr &vrwpFn) const; + bool PrintFnSharedLibrary(void); -// Attributes: -private: - const static MapPrintFnNameToPrintFn_t ms_mapPrintFnNameToPrintFn; - // - const CMIUtilString m_constStrArgNamedPrint; - bool m_bPrintFnRecognised; // True = This command has a function with a name that matches the Print argument, false = not found - bool m_bPrintFnSuccessful; // True = The print function completed its task ok, false = function failed for some reason - CMIUtilString m_strPrintFnName; - CMIUtilString m_strPrintFnError; -}; \ No newline at end of file + // Attributes: + private: + const static MapPrintFnNameToPrintFn_t ms_mapPrintFnNameToPrintFn; + // + const CMIUtilString m_constStrArgNamedPrint; + bool m_bPrintFnRecognised; // True = This command has a function with a name that matches the Print argument, false = not found + bool m_bPrintFnSuccessful; // True = The print function completed its task ok, false = function failed for some reason + CMIUtilString m_strPrintFnName; + CMIUtilString m_strPrintFnError; +}; diff --git a/tools/lldb-mi/MICmdCmdGdbSet.cpp b/tools/lldb-mi/MICmdCmdGdbSet.cpp index a256ee2e2ca1..c1c1bb599fdd 100644 --- a/tools/lldb-mi/MICmdCmdGdbSet.cpp +++ b/tools/lldb-mi/MICmdCmdGdbSet.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdGdbSet.cpp +// File: MICmdCmdGdbSet.cpp // -// Overview: CMICmdCmdGdbSet implementation. +// Overview: CMICmdCmdGdbSet implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -29,232 +29,241 @@ #include "MICmnLLDBDebugSessionInfo.h" // Instantiations: -const CMICmdCmdGdbSet::MapGdbOptionNameToFnGdbOptionPtr_t CMICmdCmdGdbSet::ms_mapGdbOptionNameToFnGdbOptionPtr = -{ - // { "target-async", &CMICmdCmdGdbSet::OptionFnTargetAsync }, // Example code if need to implement GDB set other options - // { "auto-solib-add", &CMICmdCmdGdbSet::OptionFnAutoSolibAdd }, // Example code if need to implement GDB set other options - { "solib-search-path", &CMICmdCmdGdbSet::OptionFnSolibSearchPath }, - { "fallback", &CMICmdCmdGdbSet::OptionFnFallback } -}; +const CMICmdCmdGdbSet::MapGdbOptionNameToFnGdbOptionPtr_t CMICmdCmdGdbSet::ms_mapGdbOptionNameToFnGdbOptionPtr = { + // { "target-async", &CMICmdCmdGdbSet::OptionFnTargetAsync }, // Example code if need to implement GDB set other options + // { "auto-solib-add", &CMICmdCmdGdbSet::OptionFnAutoSolibAdd }, // Example code if need to implement GDB set other options + {"solib-search-path", &CMICmdCmdGdbSet::OptionFnSolibSearchPath}, + {"fallback", &CMICmdCmdGdbSet::OptionFnFallback}}; //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdGdbSet constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdGdbSet constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdGdbSet::CMICmdCmdGdbSet( void ) -: m_constStrArgNamedThreadGrp( "thread-group" ) -, m_constStrArgNamedGdbOption( "option" ) -, m_bGdbOptionRecognised( true ) -, m_bGdbOptionFnSuccessful( false ) -, m_bGbbOptionFnHasError( false ) -, m_strGdbOptionFnError( MIRSRC( IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS ) ) +CMICmdCmdGdbSet::CMICmdCmdGdbSet(void) + : m_constStrArgNamedThreadGrp("thread-group") + , m_constStrArgNamedGdbOption("option") + , m_bGdbOptionRecognised(true) + , m_bGdbOptionFnSuccessful(false) + , m_bGbbOptionFnHasError(false) + , m_strGdbOptionFnError(MIRSRC(IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS)) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "gdb-set"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdGdbSet::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "gdb-set"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdGdbSet::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdGdbSet destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdGdbSet destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdGdbSet::~CMICmdCmdGdbSet( void ) +CMICmdCmdGdbSet::~CMICmdCmdGdbSet(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdGdbSet::ParseArgs( void ) +bool +CMICmdCmdGdbSet::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgNamedGdbOption, true, true, CMICmdArgValListBase::eArgValType_StringAnything ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add( + *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); + bOk = bOk && + m_setCmdArgs.Add( + *(new CMICmdArgValListOfN(m_constStrArgNamedGdbOption, true, true, CMICmdArgValListBase::eArgValType_StringAnything))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdGdbSet::Execute( void ) +bool +CMICmdCmdGdbSet::Execute(void) { - CMICMDBASE_GETOPTION( pArgGdbOption, ListOfN, m_constStrArgNamedGdbOption ); - const CMICmdArgValListBase::VecArgObjPtr_t & rVecWords( pArgGdbOption->GetExpectedOptions() ); - - // Get the gdb-set option to carry out - CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecWords.begin(); - const CMICmdArgValString * pOption = static_cast< const CMICmdArgValString * >( *it ); - const CMIUtilString strOption( pOption->GetValue() ); - ++it; + CMICMDBASE_GETOPTION(pArgGdbOption, ListOfN, m_constStrArgNamedGdbOption); + const CMICmdArgValListBase::VecArgObjPtr_t &rVecWords(pArgGdbOption->GetExpectedOptions()); - // Retrieve the parameter(s) for the option - CMIUtilString::VecString_t vecWords; - while( it != rVecWords.end() ) - { - const CMICmdArgValString * pWord = static_cast< const CMICmdArgValString * >( *it ); - vecWords.push_back( pWord->GetValue() ); + // Get the gdb-set option to carry out + CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecWords.begin(); + const CMICmdArgValString *pOption = static_cast(*it); + const CMIUtilString strOption(pOption->GetValue()); + ++it; - // Next - ++it; - } + // Retrieve the parameter(s) for the option + CMIUtilString::VecString_t vecWords; + while (it != rVecWords.end()) + { + const CMICmdArgValString *pWord = static_cast(*it); + vecWords.push_back(pWord->GetValue()); - FnGdbOptionPtr pPrintRequestFn = nullptr; - if( !GetOptionFn( strOption, pPrintRequestFn ) ) - { - // For unimplemented option handlers, fallback on a generic handler - // ToDo: Remove this when ALL options have been implemented - if( !GetOptionFn( "fallback", pPrintRequestFn ) ) - { - m_bGdbOptionRecognised = false; - m_strGdbOptionName = "fallback"; // This would be the strOption name - return MIstatus::success; - } - } + // Next + ++it; + } - m_bGdbOptionFnSuccessful = (this->*(pPrintRequestFn))( vecWords ); - if( !m_bGdbOptionFnSuccessful && !m_bGbbOptionFnHasError ) - return MIstatus::failure; + FnGdbOptionPtr pPrintRequestFn = nullptr; + if (!GetOptionFn(strOption, pPrintRequestFn)) + { + // For unimplemented option handlers, fallback on a generic handler + // ToDo: Remove this when ALL options have been implemented + if (!GetOptionFn("fallback", pPrintRequestFn)) + { + m_bGdbOptionRecognised = false; + m_strGdbOptionName = "fallback"; // This would be the strOption name + return MIstatus::success; + } + } - return MIstatus::success; -} + m_bGdbOptionFnSuccessful = (this->*(pPrintRequestFn))(vecWords); + if (!m_bGdbOptionFnSuccessful && !m_bGbbOptionFnHasError) + return MIstatus::failure; + + return MIstatus::success; +} //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdGdbSet::Acknowledge( void ) +bool +CMICmdCmdGdbSet::Acknowledge(void) { - if( !m_bGdbOptionRecognised ) - { - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND ), m_strGdbOptionName.c_str() ) ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - if( m_bGdbOptionFnSuccessful ) - { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } + if (!m_bGdbOptionRecognised) + { + const CMICmnMIValueConst miValueConst( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND), m_strGdbOptionName.c_str())); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + if (m_bGdbOptionFnSuccessful) + { + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INFO_PRINTFN_FAILED ), m_strGdbOptionFnError.c_str() ) ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; + const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_FAILED), m_strGdbOptionFnError.c_str())); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdGdbSet::CreateSelf( void ) +CMICmdBase * +CMICmdCmdGdbSet::CreateSelf(void) { - return new CMICmdCmdGdbSet(); + return new CMICmdCmdGdbSet(); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the print function's pointer for the matching print request. -// Type: Method. -// Args: vrPrintFnName - (R) The info requested. -// vrwpFn - (W) The print function's pointer of the function to carry out -// Return: bool - True = Print request is implemented, false = not found. -// Throws: None. +// Details: Retrieve the print function's pointer for the matching print request. +// Type: Method. +// Args: vrPrintFnName - (R) The info requested. +// vrwpFn - (W) The print function's pointer of the function to carry out +// Return: bool - True = Print request is implemented, false = not found. +// Throws: None. //-- -bool CMICmdCmdGdbSet::GetOptionFn( const CMIUtilString & vrPrintFnName, FnGdbOptionPtr & vrwpFn ) const +bool +CMICmdCmdGdbSet::GetOptionFn(const CMIUtilString &vrPrintFnName, FnGdbOptionPtr &vrwpFn) const { - vrwpFn = nullptr; + vrwpFn = nullptr; - const MapGdbOptionNameToFnGdbOptionPtr_t::const_iterator it = ms_mapGdbOptionNameToFnGdbOptionPtr.find( vrPrintFnName ); - if( it != ms_mapGdbOptionNameToFnGdbOptionPtr.end() ) - { - vrwpFn = (*it).second; - return true; - } + const MapGdbOptionNameToFnGdbOptionPtr_t::const_iterator it = ms_mapGdbOptionNameToFnGdbOptionPtr.find(vrPrintFnName); + if (it != ms_mapGdbOptionNameToFnGdbOptionPtr.end()) + { + vrwpFn = (*it).second; + return true; + } - return false; + return false; } //++ ------------------------------------------------------------------------------------ -// Details: Carry out work to complete the GDB set option 'solib-search-path' to prepare -// and send back information asked for. -// Type: Method. -// Args: vrWords - (R) List of additional parameters used by this option. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Carry out work to complete the GDB set option 'solib-search-path' to prepare +// and send back information asked for. +// Type: Method. +// Args: vrWords - (R) List of additional parameters used by this option. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdGdbSet::OptionFnSolibSearchPath( const CMIUtilString::VecString_t & vrWords ) +bool +CMICmdCmdGdbSet::OptionFnSolibSearchPath(const CMIUtilString::VecString_t &vrWords) { - // Check we have at least one argument - if( vrWords.size() < 1 ) - { - m_bGbbOptionFnHasError = true; - m_strGdbOptionFnError = MIRSRC( IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH ); - return MIstatus::failure; - } - const CMIUtilString & rStrValSolibPath( vrWords[ 0 ] ); + // Check we have at least one argument + if (vrWords.size() < 1) + { + m_bGbbOptionFnHasError = true; + m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH); + return MIstatus::failure; + } + const CMIUtilString &rStrValSolibPath(vrWords[0]); - // Add 'solib-search-path' to the shared data list - const CMIUtilString & rStrKeySolibPath( m_rLLDBDebugSessionInfo.m_constStrSharedDataSolibPath ); - if( !m_rLLDBDebugSessionInfo.SharedDataAdd< CMIUtilString >( rStrKeySolibPath, rStrValSolibPath ) ) - { - m_bGbbOptionFnHasError = false; - SetError( CMIUtilString::Format( MIRSRC( IDS_DBGSESSION_ERR_SHARED_DATA_ADD ), m_cmdData.strMiCmd.c_str(), rStrKeySolibPath.c_str() ) ); - return MIstatus::failure; - } + // Add 'solib-search-path' to the shared data list + const CMIUtilString &rStrKeySolibPath(m_rLLDBDebugSessionInfo.m_constStrSharedDataSolibPath); + if (!m_rLLDBDebugSessionInfo.SharedDataAdd(rStrKeySolibPath, rStrValSolibPath)) + { + m_bGbbOptionFnHasError = false; + SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), m_cmdData.strMiCmd.c_str(), rStrKeySolibPath.c_str())); + return MIstatus::failure; + } - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Carry out work to complete the GDB set option to prepare and send back information -// asked for. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Carry out work to complete the GDB set option to prepare and send back information +// asked for. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdGdbSet::OptionFnFallback( const CMIUtilString::VecString_t & vrWords ) +bool +CMICmdCmdGdbSet::OptionFnFallback(const CMIUtilString::VecString_t &vrWords) { - MIunused( vrWords ); + MIunused(vrWords); - // Do nothing - intentional. This is a fallback temporary action function to do nothing. - // This allows the search for gdb-set options to always suceed when the option is not - // found (implemented). + // Do nothing - intentional. This is a fallback temporary action function to do nothing. + // This allows the search for gdb-set options to always suceed when the option is not + // found (implemented). - return MIstatus::success; + return MIstatus::success; } diff --git a/tools/lldb-mi/MICmdCmdGdbSet.h b/tools/lldb-mi/MICmdCmdGdbSet.h index 24b54557bf37..59ddc57e1a2d 100644 --- a/tools/lldb-mi/MICmdCmdGdbSet.h +++ b/tools/lldb-mi/MICmdCmdGdbSet.h @@ -8,24 +8,24 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdGdbSet.h +// File: MICmdCmdGdbSet.h // -// Overview: CMICmdCmdGdbSet interface. +// Overview: CMICmdCmdGdbSet interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -34,63 +34,63 @@ #include "MICmdBase.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "gdb-set". -// This command does not follow the MI documentation exactly. While *this -// command is implemented it does not do anything with the gdb-set -// variable past in. -// The design of matching the info request to a request action (or -// command) is very simple. The request function which carries out -// the task of information gathering and printing to stdout is part of -// *this class. Should the request function become more complicated then -// that request should really reside in a command type class. Then this -// class instantiates a request info command for a matching request. The -// design/code of *this class then does not then become bloated. Use a -// lightweight version of the current MI command system. -// Gotchas: None. -// Authors: Illya Rudkin 03/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "gdb-set". +// This command does not follow the MI documentation exactly. While *this +// command is implemented it does not do anything with the gdb-set +// variable past in. +// The design of matching the info request to a request action (or +// command) is very simple. The request function which carries out +// the task of information gathering and printing to stdout is part of +// *this class. Should the request function become more complicated then +// that request should really reside in a command type class. Then this +// class instantiates a request info command for a matching request. The +// design/code of *this class then does not then become bloated. Use a +// lightweight version of the current MI command system. +// Gotchas: None. +// Authors: Illya Rudkin 03/03/2014. +// Changes: None. //-- class CMICmdCmdGdbSet : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdGdbSet( void ); + // Methods: + public: + /* ctor */ CMICmdCmdGdbSet(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdGdbSet( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdGdbSet(void); -// Typedefs: -private: - typedef bool (CMICmdCmdGdbSet::*FnGdbOptionPtr)( const CMIUtilString::VecString_t & vrWords ); - typedef std::map< CMIUtilString, FnGdbOptionPtr > MapGdbOptionNameToFnGdbOptionPtr_t; + // Typedefs: + private: + typedef bool (CMICmdCmdGdbSet::*FnGdbOptionPtr)(const CMIUtilString::VecString_t &vrWords); + typedef std::map MapGdbOptionNameToFnGdbOptionPtr_t; -// Methods: -private: - bool GetOptionFn( const CMIUtilString & vrGdbOptionName, FnGdbOptionPtr & vrwpFn ) const; - bool OptionFnSolibSearchPath( const CMIUtilString::VecString_t & vrWords ); - bool OptionFnFallback( const CMIUtilString::VecString_t & vrWords ); + // Methods: + private: + bool GetOptionFn(const CMIUtilString &vrGdbOptionName, FnGdbOptionPtr &vrwpFn) const; + bool OptionFnSolibSearchPath(const CMIUtilString::VecString_t &vrWords); + bool OptionFnFallback(const CMIUtilString::VecString_t &vrWords); -// Attributes: -private: - const static MapGdbOptionNameToFnGdbOptionPtr_t ms_mapGdbOptionNameToFnGdbOptionPtr; - // - const CMIUtilString m_constStrArgNamedThreadGrp; - const CMIUtilString m_constStrArgNamedGdbOption; - bool m_bGdbOptionRecognised; // True = This command has a function with a name that matches the Print argument, false = not found - bool m_bGdbOptionFnSuccessful; // True = The print function completed its task ok, false = function failed for some reason - bool m_bGbbOptionFnHasError; // True = The option function has an error condition (not the command!), false = option function ok. - CMIUtilString m_strGdbOptionName; - CMIUtilString m_strGdbOptionFnError; -}; \ No newline at end of file + // Attributes: + private: + const static MapGdbOptionNameToFnGdbOptionPtr_t ms_mapGdbOptionNameToFnGdbOptionPtr; + // + const CMIUtilString m_constStrArgNamedThreadGrp; + const CMIUtilString m_constStrArgNamedGdbOption; + bool m_bGdbOptionRecognised; // True = This command has a function with a name that matches the Print argument, false = not found + bool m_bGdbOptionFnSuccessful; // True = The print function completed its task ok, false = function failed for some reason + bool m_bGbbOptionFnHasError; // True = The option function has an error condition (not the command!), false = option function ok. + CMIUtilString m_strGdbOptionName; + CMIUtilString m_strGdbOptionFnError; +}; diff --git a/tools/lldb-mi/MICmdCmdGdbThread.cpp b/tools/lldb-mi/MICmdCmdGdbThread.cpp index 09bd053a65e1..e840338a2e41 100644 --- a/tools/lldb-mi/MICmdCmdGdbThread.cpp +++ b/tools/lldb-mi/MICmdCmdGdbThread.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdGdbThread.cpp +// File: MICmdCmdGdbThread.cpp // -// Overview: CMICmdCmdGdbThread implementation. +// Overview: CMICmdCmdGdbThread implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -25,76 +25,79 @@ #include "MICmnMIValueConst.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdGdbThread constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdGdbThread constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdGdbThread::CMICmdCmdGdbThread( void ) +CMICmdCmdGdbThread::CMICmdCmdGdbThread(void) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "thread"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdGdbThread::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "thread"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdGdbThread::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdThread destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdThread destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdGdbThread::~CMICmdCmdGdbThread( void ) +CMICmdCmdGdbThread::~CMICmdCmdGdbThread(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdGdbThread::Execute( void ) +bool +CMICmdCmdGdbThread::Execute(void) { - // Do nothing - - return MIstatus::success; + // Do nothing + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdGdbThread::Acknowledge( void ) +bool +CMICmdCmdGdbThread::Acknowledge(void) { - const CMICmnMIValueConst miValueConst( MIRSRC( IDS_WORD_NOT_IMPLEMENTED ) ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; + const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED)); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdGdbThread::CreateSelf( void ) +CMICmdBase * +CMICmdCmdGdbThread::CreateSelf(void) { - return new CMICmdCmdGdbThread(); -} \ No newline at end of file + return new CMICmdCmdGdbThread(); +} diff --git a/tools/lldb-mi/MICmdCmdGdbThread.h b/tools/lldb-mi/MICmdCmdGdbThread.h index 29c1361b4cf4..5fac70b8b39a 100644 --- a/tools/lldb-mi/MICmdCmdGdbThread.h +++ b/tools/lldb-mi/MICmdCmdGdbThread.h @@ -8,24 +8,24 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdGdbThread.h +// File: MICmdCmdGdbThread.h // -// Overview: CMICmdCmdGdbThread interface. +// Overview: CMICmdCmdGdbThread interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -34,28 +34,28 @@ #include "MICmdBase.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements GDB command "thread". -// Gotchas: None. -// Authors: Illya Rudkin 25/02/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements GDB command "thread". +// Gotchas: None. +// Authors: Illya Rudkin 25/02/2014. +// Changes: None. //-- class CMICmdCmdGdbThread : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdGdbThread( void ); + // Methods: + public: + /* ctor */ CMICmdCmdGdbThread(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdGdbThread( void ); -}; \ No newline at end of file + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdGdbThread(void); +}; diff --git a/tools/lldb-mi/MICmdCmdMiscellanous.cpp b/tools/lldb-mi/MICmdCmdMiscellanous.cpp index b09f585598a4..6b863a8ea8db 100644 --- a/tools/lldb-mi/MICmdCmdMiscellanous.cpp +++ b/tools/lldb-mi/MICmdCmdMiscellanous.cpp @@ -8,18 +8,18 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdMiscellanous.cpp +// File: MICmdCmdMiscellanous.cpp // -// Overview: CMICmdCmdGdbExit implementation. -// CMICmdCmdListThreadGroups implementation. -// CMICmdCmdInterpreterExec implementation. -// CMICmdCmdInferiorTtySet implementation. +// Overview: CMICmdCmdGdbExit implementation. +// CMICmdCmdListThreadGroups implementation. +// CMICmdCmdInterpreterExec implementation. +// CMICmdCmdInferiorTtySet implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third Party Headers: @@ -45,86 +45,89 @@ #include "MICmnStreamStderr.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdGdbExit constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdGdbExit constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdGdbExit::CMICmdCmdGdbExit( void ) +CMICmdCmdGdbExit::CMICmdCmdGdbExit(void) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "gdb-exit"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdGdbExit::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "gdb-exit"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdGdbExit::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdGdbExit destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdGdbExit destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdGdbExit::~CMICmdCmdGdbExit( void ) +CMICmdCmdGdbExit::~CMICmdCmdGdbExit(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdGdbExit::Execute( void ) +bool +CMICmdCmdGdbExit::Execute(void) { - CMICmnLLDBDebugger::Instance().GetDriver().SetExitApplicationFlag( true ); - const lldb::SBError sbErr = m_rLLDBDebugSessionInfo.m_lldbProcess.Detach(); - // Do not check for sbErr.Fail() here, m_lldbProcess is likely !IsValid() - - return MIstatus::success; + CMICmnLLDBDebugger::Instance().GetDriver().SetExitApplicationFlag(true); + const lldb::SBError sbErr = m_rLLDBDebugSessionInfo.m_lldbProcess.Detach(); + // Do not check for sbErr.Fail() here, m_lldbProcess is likely !IsValid() + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdGdbExit::Acknowledge( void ) +bool +CMICmdCmdGdbExit::Acknowledge(void) { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Exit ); - m_miResultRecord = miRecordResult; - - // Prod the client i.e. Eclipse with out-of-band results to help it 'continue' because it is using LLDB debugger - // Give the client '=thread-group-exited,id="i1"' - m_bHasResultRecordExtra = true; - const CMICmnMIValueConst miValueConst2( "i1" ); - const CMICmnMIValueResult miValueResult2( "id", miValueConst2 ); - const CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult2 ); - m_miResultRecordExtra = miOutOfBand.GetString(); - - return MIstatus::success; + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Exit); + m_miResultRecord = miRecordResult; + + // Prod the client i.e. Eclipse with out-of-band results to help it 'continue' because it is using LLDB debugger + // Give the client '=thread-group-exited,id="i1"' + m_bHasResultRecordExtra = true; + const CMICmnMIValueConst miValueConst2("i1"); + const CMICmnMIValueResult miValueResult2("id", miValueConst2); + const CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult2); + m_miResultRecordExtra = miOutOfBand.GetString(); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdGdbExit::CreateSelf( void ) +CMICmdBase * +CMICmdCmdGdbExit::CreateSelf(void) { - return new CMICmdCmdGdbExit(); + return new CMICmdCmdGdbExit(); } //--------------------------------------------------------------------------------------- @@ -132,258 +135,266 @@ CMICmdBase * CMICmdCmdGdbExit::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdListThreadGroups constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdListThreadGroups constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdListThreadGroups::CMICmdCmdListThreadGroups( void ) -: m_bIsI1( false ) -, m_bHaveArgOption( false ) -, m_bHaveArgRecurse( false ) -, m_constStrArgNamedAvailable( "available" ) -, m_constStrArgNamedRecurse( "recurse" ) -, m_constStrArgNamedGroup( "group" ) -, m_constStrArgNamedThreadGroup( "i1" ) +CMICmdCmdListThreadGroups::CMICmdCmdListThreadGroups(void) + : m_bIsI1(false) + , m_bHaveArgOption(false) + , m_bHaveArgRecurse(false) + , m_constStrArgNamedAvailable("available") + , m_constStrArgNamedRecurse("recurse") + , m_constStrArgNamedGroup("group") + , m_constStrArgNamedThreadGroup("i1") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "list-thread-groups"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdListThreadGroups::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "list-thread-groups"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdListThreadGroups::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdListThreadGroups destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdListThreadGroups destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdListThreadGroups::~CMICmdCmdListThreadGroups( void ) +CMICmdCmdListThreadGroups::~CMICmdCmdListThreadGroups(void) { - m_vecMIValueTuple.clear(); + m_vecMIValueTuple.clear(); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdListThreadGroups::ParseArgs( void ) +bool +CMICmdCmdListThreadGroups::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedAvailable, false, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedRecurse, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgNamedGroup, false, true, CMICmdArgValListBase::eArgValType_Number ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValThreadGrp( m_constStrArgNamedThreadGroup, false, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgNamedAvailable, false, true))); + bOk = bOk && + m_setCmdArgs.Add( + *(new CMICmdArgValOptionLong(m_constStrArgNamedRecurse, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = + bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgNamedGroup, false, true, CMICmdArgValListBase::eArgValType_Number))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValThreadGrp(m_constStrArgNamedThreadGroup, false, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Synopis: -list-thread-groups [ --available ] [ --recurse 1 ] [ group ... ] -// This command does not follow the MI documentation exactly. Has an extra -// argument "i1" to handle. -// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html#GDB_002fMI-Miscellaneous-Commands -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Synopis: -list-thread-groups [ --available ] [ --recurse 1 ] [ group ... ] +// This command does not follow the MI documentation exactly. Has an extra +// argument "i1" to handle. +// Ref: +// http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html#GDB_002fMI-Miscellaneous-Commands +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdListThreadGroups::Execute( void ) +bool +CMICmdCmdListThreadGroups::Execute(void) { - if( m_setCmdArgs.IsArgContextEmpty() ) - // No options so "top level thread groups" - return MIstatus::success; - - CMICMDBASE_GETOPTION( pArgAvailable, OptionLong, m_constStrArgNamedAvailable ); - CMICMDBASE_GETOPTION( pArgRecurse, OptionLong, m_constStrArgNamedRecurse ); - CMICMDBASE_GETOPTION( pArgThreadGroup, ThreadGrp, m_constStrArgNamedThreadGroup ); - - // Got some options so "threads" - if( pArgAvailable->GetFound() ) - { - if( pArgRecurse->GetFound() ) - { - m_bHaveArgRecurse = true; - return MIstatus::success; - } - - m_bHaveArgOption = true; - return MIstatus::success; - } - // "i1" as first argument (pos 0 of possible arg) - if( !pArgThreadGroup->GetFound() ) - return MIstatus::success; - m_bIsI1 = true; - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; - - // Note do not check for rProcess is IsValid(), continue - - m_vecMIValueTuple.clear(); - const MIuint nThreads = rProcess.GetNumThreads(); - for( MIuint i = 0; i < nThreads; i++ ) - { - // GetThreadAtIndex() uses a base 0 index - // GetThreadByIndexID() uses a base 1 index - lldb::SBThread thread = rProcess.GetThreadAtIndex( i ); - - if( thread.IsValid() ) - { - CMICmnMIValueTuple miTuple; - if( !rSessionInfo.MIResponseFormThreadInfo2( m_cmdData, thread, miTuple ) ) - return MIstatus::failure; - - m_vecMIValueTuple.push_back( miTuple ); - } - } - - return MIstatus::success; + if (m_setCmdArgs.IsArgContextEmpty()) + // No options so "top level thread groups" + return MIstatus::success; + + CMICMDBASE_GETOPTION(pArgAvailable, OptionLong, m_constStrArgNamedAvailable); + CMICMDBASE_GETOPTION(pArgRecurse, OptionLong, m_constStrArgNamedRecurse); + CMICMDBASE_GETOPTION(pArgThreadGroup, ThreadGrp, m_constStrArgNamedThreadGroup); + + // Got some options so "threads" + if (pArgAvailable->GetFound()) + { + if (pArgRecurse->GetFound()) + { + m_bHaveArgRecurse = true; + return MIstatus::success; + } + + m_bHaveArgOption = true; + return MIstatus::success; + } + // "i1" as first argument (pos 0 of possible arg) + if (!pArgThreadGroup->GetFound()) + return MIstatus::success; + m_bIsI1 = true; + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + + // Note do not check for rProcess is IsValid(), continue + + m_vecMIValueTuple.clear(); + const MIuint nThreads = rProcess.GetNumThreads(); + for (MIuint i = 0; i < nThreads; i++) + { + // GetThreadAtIndex() uses a base 0 index + // GetThreadByIndexID() uses a base 1 index + lldb::SBThread thread = rProcess.GetThreadAtIndex(i); + + if (thread.IsValid()) + { + CMICmnMIValueTuple miTuple; + if (!rSessionInfo.MIResponseFormThreadInfo2(m_cmdData, thread, miTuple)) + return MIstatus::failure; + + m_vecMIValueTuple.push_back(miTuple); + } + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdListThreadGroups::Acknowledge( void ) +bool +CMICmdCmdListThreadGroups::Acknowledge(void) { - if( m_bHaveArgOption ) - { - if( m_bHaveArgRecurse ) - { - const CMICmnMIValueConst miValueConst( MIRSRC( IDS_WORD_NOT_IMPLEMENTED_BRKTS ) ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; - } - - const CMICmnMIValueConst miValueConst1( "i1" ); - const CMICmnMIValueResult miValueResult1( "id", miValueConst1 ); - CMICmnMIValueTuple miTuple( miValueResult1 ); - - const CMICmnMIValueConst miValueConst2( "process" ); - const CMICmnMIValueResult miValueResult2( "type", miValueConst2 ); - miTuple.Add( miValueResult2 ); - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - if (rSessionInfo.m_lldbProcess.IsValid ()) - { - const lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID(); - const CMIUtilString strPid( CMIUtilString::Format( "%lld", pid ) ); - const CMICmnMIValueConst miValueConst3( strPid ); - const CMICmnMIValueResult miValueResult3( "pid", miValueConst3 ); - miTuple.Add( miValueResult3 ); - } - - const CMICmnMIValueConst miValueConst4( MIRSRC( IDS_WORD_NOT_IMPLEMENTED_BRKTS ) ); - const CMICmnMIValueResult miValueResult4( "num_children", miValueConst4 ); - miTuple.Add( miValueResult4 ); - - const CMICmnMIValueConst miValueConst5( MIRSRC( IDS_WORD_NOT_IMPLEMENTED_BRKTS ) ); - const CMICmnMIValueResult miValueResult5( "cores", miValueConst5 ); - miTuple.Add( miValueResult5 ); - - const CMICmnMIValueList miValueList( miTuple ); - const CMICmnMIValueResult miValueResult6( "groups", miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6 ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; - } - - if( !m_bIsI1 ) - { - const CMICmnMIValueConst miValueConst1( "i1" ); - const CMICmnMIValueResult miValueResult1( "id", miValueConst1 ); - CMICmnMIValueTuple miTuple( miValueResult1 ); - - const CMICmnMIValueConst miValueConst2( "process" ); - const CMICmnMIValueResult miValueResult2( "type", miValueConst2 ); - miTuple.Add( miValueResult2 ); - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - if (rSessionInfo.m_lldbProcess.IsValid ()) - { - const lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID(); - const CMIUtilString strPid( CMIUtilString::Format( "%lld", pid ) ); - const CMICmnMIValueConst miValueConst3( strPid ); - const CMICmnMIValueResult miValueResult3( "pid", miValueConst3 ); - miTuple.Add( miValueResult3 ); - } - - if (rSessionInfo.m_lldbTarget.IsValid ()) - { - lldb::SBTarget & rTrgt = rSessionInfo.m_lldbTarget; - const MIchar * pDir = rTrgt.GetExecutable().GetDirectory(); - const MIchar * pFileName = rTrgt.GetExecutable().GetFilename(); - const CMIUtilString strFile( CMIUtilString::Format( "%s/%s", pDir, pFileName ) ); - const CMICmnMIValueConst miValueConst4( strFile ); - const CMICmnMIValueResult miValueResult4( "executable", miValueConst4 ); - miTuple.Add( miValueResult4 ); - } - - const CMICmnMIValueList miValueList( miTuple ); - const CMICmnMIValueResult miValueResult5( "groups", miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult5 ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - // Build up a list of thread information from tuples - VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin(); - if( it == m_vecMIValueTuple.end() ) - { - const CMICmnMIValueConst miValueConst( "[]" ); - const CMICmnMIValueResult miValueResult( "threads", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - CMICmnMIValueList miValueList( *it ); - ++it; - while( it != m_vecMIValueTuple.end() ) - { - const CMICmnMIValueTuple & rTuple( *it ); - miValueList.Add( rTuple ); - - // Next - ++it; - } - - const CMICmnMIValueResult miValueResult( "threads", miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + if (m_bHaveArgOption) + { + if (m_bHaveArgRecurse) + { + const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED_BRKTS)); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; + } + + const CMICmnMIValueConst miValueConst1("i1"); + const CMICmnMIValueResult miValueResult1("id", miValueConst1); + CMICmnMIValueTuple miTuple(miValueResult1); + + const CMICmnMIValueConst miValueConst2("process"); + const CMICmnMIValueResult miValueResult2("type", miValueConst2); + miTuple.Add(miValueResult2); + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + if (rSessionInfo.m_lldbProcess.IsValid()) + { + const lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID(); + const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); + const CMICmnMIValueConst miValueConst3(strPid); + const CMICmnMIValueResult miValueResult3("pid", miValueConst3); + miTuple.Add(miValueResult3); + } + + const CMICmnMIValueConst miValueConst4(MIRSRC(IDS_WORD_NOT_IMPLEMENTED_BRKTS)); + const CMICmnMIValueResult miValueResult4("num_children", miValueConst4); + miTuple.Add(miValueResult4); + + const CMICmnMIValueConst miValueConst5(MIRSRC(IDS_WORD_NOT_IMPLEMENTED_BRKTS)); + const CMICmnMIValueResult miValueResult5("cores", miValueConst5); + miTuple.Add(miValueResult5); + + const CMICmnMIValueList miValueList(miTuple); + const CMICmnMIValueResult miValueResult6("groups", miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6); + m_miResultRecord = miRecordResult; + + return MIstatus::success; + } + + if (!m_bIsI1) + { + const CMICmnMIValueConst miValueConst1("i1"); + const CMICmnMIValueResult miValueResult1("id", miValueConst1); + CMICmnMIValueTuple miTuple(miValueResult1); + + const CMICmnMIValueConst miValueConst2("process"); + const CMICmnMIValueResult miValueResult2("type", miValueConst2); + miTuple.Add(miValueResult2); + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + if (rSessionInfo.m_lldbProcess.IsValid()) + { + const lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID(); + const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); + const CMICmnMIValueConst miValueConst3(strPid); + const CMICmnMIValueResult miValueResult3("pid", miValueConst3); + miTuple.Add(miValueResult3); + } + + if (rSessionInfo.m_lldbTarget.IsValid()) + { + lldb::SBTarget &rTrgt = rSessionInfo.m_lldbTarget; + const MIchar *pDir = rTrgt.GetExecutable().GetDirectory(); + const MIchar *pFileName = rTrgt.GetExecutable().GetFilename(); + const CMIUtilString strFile(CMIUtilString::Format("%s/%s", pDir, pFileName)); + const CMICmnMIValueConst miValueConst4(strFile); + const CMICmnMIValueResult miValueResult4("executable", miValueConst4); + miTuple.Add(miValueResult4); + } + + const CMICmnMIValueList miValueList(miTuple); + const CMICmnMIValueResult miValueResult5("groups", miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult5); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + // Build up a list of thread information from tuples + VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin(); + if (it == m_vecMIValueTuple.end()) + { + const CMICmnMIValueConst miValueConst("[]"); + const CMICmnMIValueResult miValueResult("threads", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + CMICmnMIValueList miValueList(*it); + ++it; + while (it != m_vecMIValueTuple.end()) + { + const CMICmnMIValueTuple &rTuple(*it); + miValueList.Add(rTuple); + + // Next + ++it; + } + + const CMICmnMIValueResult miValueResult("threads", miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdListThreadGroups::CreateSelf( void ) +CMICmdBase * +CMICmdCmdListThreadGroups::CreateSelf(void) { - return new CMICmdCmdListThreadGroups(); + return new CMICmdCmdListThreadGroups(); } //--------------------------------------------------------------------------------------- @@ -391,123 +402,130 @@ CMICmdBase * CMICmdCmdListThreadGroups::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdInterpreterExec constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdInterpreterExec constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdInterpreterExec::CMICmdCmdInterpreterExec( void ) -: m_constStrArgNamedInterpreter( "intepreter" ) -, m_constStrArgNamedCommand( "command" ) +CMICmdCmdInterpreterExec::CMICmdCmdInterpreterExec(void) + : m_constStrArgNamedInterpreter("intepreter") + , m_constStrArgNamedCommand("command") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "interpreter-exec"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdInterpreterExec::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "interpreter-exec"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdInterpreterExec::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdInterpreterExec destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdInterpreterExec destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdInterpreterExec::~CMICmdCmdInterpreterExec( void ) +CMICmdCmdInterpreterExec::~CMICmdCmdInterpreterExec(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdInterpreterExec::ParseArgs( void ) +bool +CMICmdCmdInterpreterExec::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedInterpreter, true, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedCommand, true, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedInterpreter, true, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedCommand, true, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdInterpreterExec::Execute( void ) +bool +CMICmdCmdInterpreterExec::Execute(void) { - CMICMDBASE_GETOPTION( pArgInterpreter, String, m_constStrArgNamedInterpreter ); - CMICMDBASE_GETOPTION( pArgCommand, String, m_constStrArgNamedCommand ); - - // Handle the interpreter parameter by do nothing on purpose (set to 'handled' in - // the arg definition above) - const CMIUtilString & rStrInterpreter( pArgInterpreter->GetValue() ); MIunused( rStrInterpreter ); - - const CMIUtilString & rStrCommand( pArgCommand->GetValue() ); - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - const lldb::ReturnStatus rtn = rSessionInfo.m_rLldbDebugger.GetCommandInterpreter().HandleCommand( rStrCommand.c_str(), m_lldbResult, true ); MIunused( rtn ); - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgInterpreter, String, m_constStrArgNamedInterpreter); + CMICMDBASE_GETOPTION(pArgCommand, String, m_constStrArgNamedCommand); + + // Handle the interpreter parameter by do nothing on purpose (set to 'handled' in + // the arg definition above) + const CMIUtilString &rStrInterpreter(pArgInterpreter->GetValue()); + MIunused(rStrInterpreter); + + const CMIUtilString &rStrCommand(pArgCommand->GetValue()); + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + const lldb::ReturnStatus rtn = + rSessionInfo.m_rLldbDebugger.GetCommandInterpreter().HandleCommand(rStrCommand.c_str(), m_lldbResult, true); + MIunused(rtn); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdInterpreterExec::Acknowledge( void ) +bool +CMICmdCmdInterpreterExec::Acknowledge(void) { - if( m_lldbResult.GetOutputSize() > 0 ) - { - CMIUtilString strMsg( m_lldbResult.GetOutput() ); - strMsg = strMsg.StripCREndOfLine(); - CMICmnStreamStdout::TextToStdout( strMsg ); - - // Send the LLDB result message to console so the user can see the result of the - // command they typed. It is not necessary an error message. - CMICmnStreamStderr::LLDBMsgToConsole( strMsg ); - } - if( m_lldbResult.GetErrorSize() > 0 ) - { - CMIUtilString strMsg( m_lldbResult.GetError() ); - strMsg = strMsg.StripCREndOfLine(); - CMICmnStreamStderr::LLDBMsgToConsole( strMsg ); - - // Send LLDB's error message to the MI Driver's Log file - CMICmnStreamStdout::TextToStdout( strMsg ); - } - - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + if (m_lldbResult.GetOutputSize() > 0) + { + CMIUtilString strMsg(m_lldbResult.GetOutput()); + strMsg = strMsg.StripCREndOfLine(); + CMICmnStreamStdout::TextToStdout(strMsg); + + // Send the LLDB result message to console so the user can see the result of the + // command they typed. It is not necessary an error message. + CMICmnStreamStderr::LLDBMsgToConsole(strMsg); + } + if (m_lldbResult.GetErrorSize() > 0) + { + CMIUtilString strMsg(m_lldbResult.GetError()); + strMsg = strMsg.StripCREndOfLine(); + CMICmnStreamStderr::LLDBMsgToConsole(strMsg); + + // Send LLDB's error message to the MI Driver's Log file + CMICmnStreamStdout::TextToStdout(strMsg); + } + + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdInterpreterExec::CreateSelf( void ) +CMICmdBase * +CMICmdCmdInterpreterExec::CreateSelf(void) { - return new CMICmdCmdInterpreterExec(); + return new CMICmdCmdInterpreterExec(); } //--------------------------------------------------------------------------------------- @@ -515,74 +533,77 @@ CMICmdBase * CMICmdCmdInterpreterExec::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdInferiorTtySet constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdInferiorTtySet constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdInferiorTtySet::CMICmdCmdInferiorTtySet( void ) +CMICmdCmdInferiorTtySet::CMICmdCmdInferiorTtySet(void) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "inferior-tty-set"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdInferiorTtySet::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "inferior-tty-set"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdInferiorTtySet::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdInferiorTtySet destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdInferiorTtySet destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdInferiorTtySet::~CMICmdCmdInferiorTtySet( void ) +CMICmdCmdInferiorTtySet::~CMICmdCmdInferiorTtySet(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdInferiorTtySet::Execute( void ) +bool +CMICmdCmdInferiorTtySet::Execute(void) { - // Do nothing - - return MIstatus::success; + // Do nothing + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdInferiorTtySet::Acknowledge( void ) +bool +CMICmdCmdInferiorTtySet::Acknowledge(void) { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done ); - m_miResultRecord = miRecordResult; + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdInferiorTtySet::CreateSelf( void ) +CMICmdBase * +CMICmdCmdInferiorTtySet::CreateSelf(void) { - return new CMICmdCmdInferiorTtySet(); + return new CMICmdCmdInferiorTtySet(); } diff --git a/tools/lldb-mi/MICmdCmdMiscellanous.h b/tools/lldb-mi/MICmdCmdMiscellanous.h index ea71f1233418..1cabbac7e80a 100644 --- a/tools/lldb-mi/MICmdCmdMiscellanous.h +++ b/tools/lldb-mi/MICmdCmdMiscellanous.h @@ -8,27 +8,27 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdMiscellanous.h +// File: MICmdCmdMiscellanous.h // -// Overview: CMICmdCmdGdbExit interface. -// CMICmdCmdListThreadGroups interface. -// CMICmdCmdInterpreterExec interface. -// CMICmdCmdInferiorTtySet interface. +// Overview: CMICmdCmdGdbExit interface. +// CMICmdCmdListThreadGroups interface. +// CMICmdCmdInterpreterExec interface. +// CMICmdCmdInferiorTtySet interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -42,134 +42,134 @@ #include "MICmnMIValueList.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "gdb-exit". -// Gotchas: None. -// Authors: Illya Rudkin 04/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "gdb-exit". +// Gotchas: None. +// Authors: Illya Rudkin 04/03/2014. +// Changes: None. //-- class CMICmdCmdGdbExit : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdGdbExit( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdGdbExit( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdGdbExit(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdGdbExit(void); }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "list-thread-groups". -// This command does not follow the MI documentation exactly. -// http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html#GDB_002fMI-Miscellaneous-Commands -// Gotchas: None. -// Authors: Illya Rudkin 06/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "list-thread-groups". +// This command does not follow the MI documentation exactly. +// http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html#GDB_002fMI-Miscellaneous-Commands +// Gotchas: None. +// Authors: Illya Rudkin 06/03/2014. +// Changes: None. //-- class CMICmdCmdListThreadGroups : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdListThreadGroups( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdListThreadGroups( void ); - -// Typedefs: -private: - typedef std::vector< CMICmnMIValueTuple > VecMIValueTuple_t; - -// Attributes: -private: - bool m_bIsI1; // True = Yes command argument equal "i1", false = no match - bool m_bHaveArgOption; // True = Yes "--available" present, false = not found - bool m_bHaveArgRecurse; // True = Yes command argument "--recurse", false = no found - VecMIValueTuple_t m_vecMIValueTuple; - const CMIUtilString m_constStrArgNamedAvailable; - const CMIUtilString m_constStrArgNamedRecurse; - const CMIUtilString m_constStrArgNamedGroup; - const CMIUtilString m_constStrArgNamedThreadGroup; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdListThreadGroups(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdListThreadGroups(void); + + // Typedefs: + private: + typedef std::vector VecMIValueTuple_t; + + // Attributes: + private: + bool m_bIsI1; // True = Yes command argument equal "i1", false = no match + bool m_bHaveArgOption; // True = Yes "--available" present, false = not found + bool m_bHaveArgRecurse; // True = Yes command argument "--recurse", false = no found + VecMIValueTuple_t m_vecMIValueTuple; + const CMIUtilString m_constStrArgNamedAvailable; + const CMIUtilString m_constStrArgNamedRecurse; + const CMIUtilString m_constStrArgNamedGroup; + const CMIUtilString m_constStrArgNamedThreadGroup; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "interpreter-exec". -// Gotchas: None. -// Authors: Illya Rudkin 16/05/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "interpreter-exec". +// Gotchas: None. +// Authors: Illya Rudkin 16/05/2014. +// Changes: None. //-- class CMICmdCmdInterpreterExec : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdInterpreterExec( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdInterpreterExec( void ); - -// Attributes: -private: - const CMIUtilString m_constStrArgNamedInterpreter; - const CMIUtilString m_constStrArgNamedCommand; - lldb::SBCommandReturnObject m_lldbResult; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdInterpreterExec(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdInterpreterExec(void); + + // Attributes: + private: + const CMIUtilString m_constStrArgNamedInterpreter; + const CMIUtilString m_constStrArgNamedCommand; + lldb::SBCommandReturnObject m_lldbResult; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "inferior-tty-set". -// Gotchas: None. -// Authors: Illya Rudkin 22/07/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "inferior-tty-set". +// Gotchas: None. +// Authors: Illya Rudkin 22/07/2014. +// Changes: None. //-- class CMICmdCmdInferiorTtySet : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdInferiorTtySet( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdInferiorTtySet( void ); -}; \ No newline at end of file + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdInferiorTtySet(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdInferiorTtySet(void); +}; diff --git a/tools/lldb-mi/MICmdCmdStack.cpp b/tools/lldb-mi/MICmdCmdStack.cpp index 5f5b355758c4..4ed6803a1edb 100644 --- a/tools/lldb-mi/MICmdCmdStack.cpp +++ b/tools/lldb-mi/MICmdCmdStack.cpp @@ -8,18 +8,18 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdStack.cpp +// File: MICmdCmdStack.cpp // -// Overview: CMICmdCmdStackInfoDepth implementation. -// CMICmdCmdStackListFrames implementation. -// CMICmdCmdStackListArguments implementation. -// CMICmdCmdStackListLocals implementation. +// Overview: CMICmdCmdStackInfoDepth implementation. +// CMICmdCmdStackListFrames implementation. +// CMICmdCmdStackListArguments implementation. +// CMICmdCmdStackListLocals implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third Party Headers: @@ -40,112 +40,117 @@ #include "MICmdArgValListOfN.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdStackInfoDepth constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdStackInfoDepth constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdStackInfoDepth::CMICmdCmdStackInfoDepth( void ) -: m_nThreadFrames( 0 ) -, m_constStrArgThread( "thread" ) -, m_constStrArgMaxDepth( "max-depth" ) +CMICmdCmdStackInfoDepth::CMICmdCmdStackInfoDepth(void) + : m_nThreadFrames(0) + , m_constStrArgThread("thread") + , m_constStrArgMaxDepth("max-depth") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "stack-info-depth"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdStackInfoDepth::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "stack-info-depth"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdStackInfoDepth::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdStackInfoDepth destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdStackInfoDepth destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdStackInfoDepth::~CMICmdCmdStackInfoDepth( void ) +CMICmdCmdStackInfoDepth::~CMICmdCmdStackInfoDepth(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdStackInfoDepth::ParseArgs( void ) +bool +CMICmdCmdStackInfoDepth::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgMaxDepth, false, false ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgMaxDepth, false, false))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdStackInfoDepth::Execute( void ) +bool +CMICmdCmdStackInfoDepth::Execute(void) { - CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread ); - CMICMDBASE_GETOPTION( pArgMaxDepth, Number, m_constStrArgMaxDepth ); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) ); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID( nThreadId ) : rProcess.GetSelectedThread(); - m_nThreadFrames = thread.GetNumFrames(); - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + CMICMDBASE_GETOPTION(pArgMaxDepth, Number, m_constStrArgMaxDepth); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (!pArgThread->GetExpectedOption(nThreadId)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID(nThreadId) : rProcess.GetSelectedThread(); + m_nThreadFrames = thread.GetNumFrames(); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdStackInfoDepth::Acknowledge( void ) +bool +CMICmdCmdStackInfoDepth::Acknowledge(void) { - const CMIUtilString strDepth( CMIUtilString::Format( "%d", m_nThreadFrames ) ); - const CMICmnMIValueConst miValueConst( strDepth ); - const CMICmnMIValueResult miValueResult( "depth", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; + const CMIUtilString strDepth(CMIUtilString::Format("%d", m_nThreadFrames)); + const CMICmnMIValueConst miValueConst(strDepth); + const CMICmnMIValueResult miValueResult("depth", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdStackInfoDepth::CreateSelf( void ) +CMICmdBase * +CMICmdCmdStackInfoDepth::CreateSelf(void) { - return new CMICmdCmdStackInfoDepth(); + return new CMICmdCmdStackInfoDepth(); } //--------------------------------------------------------------------------------------- @@ -153,175 +158,180 @@ CMICmdBase * CMICmdCmdStackInfoDepth::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdStackListFrames constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdStackListFrames constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdStackListFrames::CMICmdCmdStackListFrames( void ) -: m_nThreadFrames( 0 ) -, m_constStrArgThread( "thread" ) -, m_constStrArgFrameLow( "low-frame" ) -, m_constStrArgFrameHigh( "high-frame" ) +CMICmdCmdStackListFrames::CMICmdCmdStackListFrames(void) + : m_nThreadFrames(0) + , m_constStrArgThread("thread") + , m_constStrArgFrameLow("low-frame") + , m_constStrArgFrameHigh("high-frame") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "stack-list-frames"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdStackListFrames::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "stack-list-frames"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdStackListFrames::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdStackListFrames destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdStackListFrames destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdStackListFrames::~CMICmdCmdStackListFrames( void ) +CMICmdCmdStackListFrames::~CMICmdCmdStackListFrames(void) { - m_vecMIValueResult.clear(); + m_vecMIValueResult.clear(); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdStackListFrames::ParseArgs( void ) +bool +CMICmdCmdStackListFrames::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgFrameLow, false, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgFrameHigh, false, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgFrameLow, false, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgFrameHigh, false, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdStackListFrames::Execute( void ) +bool +CMICmdCmdStackListFrames::Execute(void) { - CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread ); - CMICMDBASE_GETOPTION( pArgFrameLow, Number, m_constStrArgFrameLow ); - CMICMDBASE_GETOPTION( pArgFrameHigh, Number, m_constStrArgFrameHigh ); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) ); - return MIstatus::failure; - } - - // Frame low and high options are not mandatory - MIuint nFrameHigh = pArgFrameHigh->GetFound() ? pArgFrameHigh->GetValue() : UINT64_MAX; - const MIuint nFrameLow = pArgFrameLow->GetFound() ? pArgFrameLow->GetValue() : 0; - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID( nThreadId ) : rProcess.GetSelectedThread(); - MIuint nThreadFrames = thread.GetNumFrames(); - - // Adjust nThreadFrames for the nFrameHigh argument as we use nFrameHigh+1 in the min calc as the arg + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + CMICMDBASE_GETOPTION(pArgFrameLow, Number, m_constStrArgFrameLow); + CMICMDBASE_GETOPTION(pArgFrameHigh, Number, m_constStrArgFrameHigh); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (!pArgThread->GetExpectedOption(nThreadId)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); + return MIstatus::failure; + } + + // Frame low and high options are not mandatory + MIuint nFrameHigh = pArgFrameHigh->GetFound() ? pArgFrameHigh->GetValue() : UINT32_MAX; + const MIuint nFrameLow = pArgFrameLow->GetFound() ? pArgFrameLow->GetValue() : 0; + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID(nThreadId) : rProcess.GetSelectedThread(); + MIuint nThreadFrames = thread.GetNumFrames(); + + // Adjust nThreadFrames for the nFrameHigh argument as we use nFrameHigh+1 in the min calc as the arg // is not an index, but a frame id value. - if( nFrameHigh < UINT32_MAX ) - { - nFrameHigh++; - nThreadFrames = (nFrameHigh < nThreadFrames) ? nFrameHigh : nThreadFrames; - } - - m_nThreadFrames = nThreadFrames; - if( nThreadFrames == 0 ) - return MIstatus::success; - - m_vecMIValueResult.clear(); - for( MIuint nLevel = nFrameLow; nLevel < nThreadFrames; nLevel++ ) - { - CMICmnMIValueTuple miValueTuple; - if( !rSessionInfo.MIResponseFormFrameInfo( thread, nLevel, miValueTuple ) ) - return MIstatus::failure; - - const CMICmnMIValueResult miValueResult8( "frame", miValueTuple ); - m_vecMIValueResult.push_back( miValueResult8 ); - } - - return MIstatus::success; + if (nFrameHigh < UINT32_MAX) + { + nFrameHigh++; + nThreadFrames = (nFrameHigh < nThreadFrames) ? nFrameHigh : nThreadFrames; + } + + m_nThreadFrames = nThreadFrames; + if (nThreadFrames == 0) + return MIstatus::success; + + m_vecMIValueResult.clear(); + for (MIuint nLevel = nFrameLow; nLevel < nThreadFrames; nLevel++) + { + CMICmnMIValueTuple miValueTuple; + if (!rSessionInfo.MIResponseFormFrameInfo(thread, nLevel, miValueTuple)) + return MIstatus::failure; + + const CMICmnMIValueResult miValueResult8("frame", miValueTuple); + m_vecMIValueResult.push_back(miValueResult8); + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdStackListFrames::Acknowledge( void ) +bool +CMICmdCmdStackListFrames::Acknowledge(void) { - if( m_nThreadFrames == 0 ) - { - // MI print "3^done,stack=[{}]" - const CMICmnMIValueTuple miValueTuple; - const CMICmnMIValueList miValueList( miValueTuple ); - const CMICmnMIValueResult miValueResult( "stack", miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; - } - - // Build up a list of thread information from tuples - VecMIValueResult_t::const_iterator it = m_vecMIValueResult.begin(); - if( it == m_vecMIValueResult.end() ) - { - // MI print "3^done,stack=[{}]" - const CMICmnMIValueTuple miValueTuple; - const CMICmnMIValueList miValueList( miValueTuple ); - const CMICmnMIValueResult miValueResult( "stack", miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - CMICmnMIValueList miValueList( *it ); - ++it; - while( it != m_vecMIValueResult.end() ) - { - const CMICmnMIValueResult & rTuple( *it ); - miValueList.Add( rTuple ); - - // Next - ++it; - } - const CMICmnMIValueResult miValueResult( "stack", miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + if (m_nThreadFrames == 0) + { + // MI print "3^done,stack=[{}]" + const CMICmnMIValueTuple miValueTuple; + const CMICmnMIValueList miValueList(miValueTuple); + const CMICmnMIValueResult miValueResult("stack", miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; + } + + // Build up a list of thread information from tuples + VecMIValueResult_t::const_iterator it = m_vecMIValueResult.begin(); + if (it == m_vecMIValueResult.end()) + { + // MI print "3^done,stack=[{}]" + const CMICmnMIValueTuple miValueTuple; + const CMICmnMIValueList miValueList(miValueTuple); + const CMICmnMIValueResult miValueResult("stack", miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + CMICmnMIValueList miValueList(*it); + ++it; + while (it != m_vecMIValueResult.end()) + { + const CMICmnMIValueResult &rTuple(*it); + miValueList.Add(rTuple); + + // Next + ++it; + } + const CMICmnMIValueResult miValueResult("stack", miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdStackListFrames::CreateSelf( void ) +CMICmdBase * +CMICmdCmdStackListFrames::CreateSelf(void) { - return new CMICmdCmdStackListFrames(); + return new CMICmdCmdStackListFrames(); } //--------------------------------------------------------------------------------------- @@ -329,152 +339,156 @@ CMICmdBase * CMICmdCmdStackListFrames::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdStackListArguments constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdStackListArguments constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdStackListArguments::CMICmdCmdStackListArguments( void ) -: m_bThreadInvalid( false ) -, m_miValueList( true ) -, m_constStrArgThread( "thread" ) -, m_constStrArgPrintValues( "print-values" ) +CMICmdCmdStackListArguments::CMICmdCmdStackListArguments(void) + : m_bThreadInvalid(false) + , m_miValueList(true) + , m_constStrArgThread("thread") + , m_constStrArgPrintValues("print-values") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "stack-list-arguments"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdStackListArguments::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "stack-list-arguments"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdStackListArguments::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdStackListArguments destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdStackListArguments destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdStackListArguments::~CMICmdCmdStackListArguments( void ) +CMICmdCmdStackListArguments::~CMICmdCmdStackListArguments(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdStackListArguments::ParseArgs( void ) +bool +CMICmdCmdStackListArguments::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgPrintValues, true, false ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgPrintValues, true, false))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdStackListArguments::Execute( void ) +bool +CMICmdCmdStackListArguments::Execute(void) { - CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread ); - CMICMDBASE_GETOPTION( pArgPrintValues, Number, m_constStrArgPrintValues ); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if( pArgThread->GetFound() ) - { - if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) ); - return MIstatus::failure; - } - } - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID( nThreadId ) : rProcess.GetSelectedThread(); - m_bThreadInvalid = !thread.IsValid(); - if( m_bThreadInvalid ) - return MIstatus::success; - - const lldb::StopReason eStopReason = thread.GetStopReason(); - if( (eStopReason == lldb::eStopReasonNone) || (eStopReason == lldb::eStopReasonInvalid) ) - { - m_bThreadInvalid = true; - return MIstatus::success; - } - - - const MIuint nFrames = thread.GetNumFrames(); - for( MIuint i = 0; i < nFrames; i++ ) - { - lldb::SBFrame frame = thread.GetFrameAtIndex( i ); - CMICmnMIValueList miValueList( true ); - const MIuint maskVarTypes = 0x1000; - if( !rSessionInfo.MIResponseFormVariableInfo3( frame, maskVarTypes, miValueList ) ) - return MIstatus::failure; - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", i ) ); - const CMICmnMIValueResult miValueResult( "level", miValueConst ); - CMICmnMIValueTuple miValueTuple( miValueResult ); - const CMICmnMIValueResult miValueResult2( "args", miValueList ); - miValueTuple.Add( miValueResult2 ); - const CMICmnMIValueResult miValueResult3( "frame", miValueTuple ); - m_miValueList.Add( miValueResult3 ); - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + CMICMDBASE_GETOPTION(pArgPrintValues, Number, m_constStrArgPrintValues); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (pArgThread->GetFound()) + { + if (!pArgThread->GetExpectedOption(nThreadId)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); + return MIstatus::failure; + } + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID(nThreadId) : rProcess.GetSelectedThread(); + m_bThreadInvalid = !thread.IsValid(); + if (m_bThreadInvalid) + return MIstatus::success; + + const lldb::StopReason eStopReason = thread.GetStopReason(); + if ((eStopReason == lldb::eStopReasonNone) || (eStopReason == lldb::eStopReasonInvalid)) + { + m_bThreadInvalid = true; + return MIstatus::success; + } + + const MIuint nFrames = thread.GetNumFrames(); + for (MIuint i = 0; i < nFrames; i++) + { + lldb::SBFrame frame = thread.GetFrameAtIndex(i); + CMICmnMIValueList miValueList(true); + const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments; + if (!rSessionInfo.MIResponseFormVariableInfo3(frame, maskVarTypes, miValueList)) + return MIstatus::failure; + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", i)); + const CMICmnMIValueResult miValueResult("level", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueResult miValueResult2("args", miValueList); + miValueTuple.Add(miValueResult2); + const CMICmnMIValueResult miValueResult3("frame", miValueTuple); + m_miValueList.Add(miValueResult3); + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdStackListArguments::Acknowledge( void ) +bool +CMICmdCmdStackListArguments::Acknowledge(void) { - if( m_bThreadInvalid ) - { - // MI print "%s^done,stack-args=[]" - const CMICmnMIValueList miValueList( true ); - const CMICmnMIValueResult miValueResult( "stack-args", miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - // MI print "%s^done,stack-args=[frame={level=\"0\",args=[%s]},frame={level=\"1\",args=[%s]}]" - const CMICmnMIValueResult miValueResult4( "stack-args", m_miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult4 ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + if (m_bThreadInvalid) + { + // MI print "%s^done,stack-args=[]" + const CMICmnMIValueList miValueList(true); + const CMICmnMIValueResult miValueResult("stack-args", miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + // MI print "%s^done,stack-args=[frame={level=\"0\",args=[%s]},frame={level=\"1\",args=[%s]}]" + const CMICmnMIValueResult miValueResult4("stack-args", m_miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult4); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdStackListArguments::CreateSelf( void ) +CMICmdBase * +CMICmdCmdStackListArguments::CreateSelf(void) { - return new CMICmdCmdStackListArguments(); + return new CMICmdCmdStackListArguments(); } //--------------------------------------------------------------------------------------- @@ -482,153 +496,159 @@ CMICmdBase * CMICmdCmdStackListArguments::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdStackListLocals constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdStackListLocals constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdStackListLocals::CMICmdCmdStackListLocals( void ) -: m_bThreadInvalid( false ) -, m_miValueList( true ) -, m_constStrArgThread( "thread" ) -, m_constStrArgFrame( "frame" ) -, m_constStrArgPrintValues( "print-values" ) +CMICmdCmdStackListLocals::CMICmdCmdStackListLocals(void) + : m_bThreadInvalid(false) + , m_miValueList(true) + , m_constStrArgThread("thread") + , m_constStrArgFrame("frame") + , m_constStrArgPrintValues("print-values") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "stack-list-locals"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdStackListLocals::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "stack-list-locals"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdStackListLocals::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdStackListLocals destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdStackListLocals destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdStackListLocals::~CMICmdCmdStackListLocals( void ) +CMICmdCmdStackListLocals::~CMICmdCmdStackListLocals(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdStackListLocals::ParseArgs( void ) +bool +CMICmdCmdStackListLocals::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgFrame, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgPrintValues, true, false ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgFrame, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgPrintValues, true, false))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdStackListLocals::Execute( void ) +bool +CMICmdCmdStackListLocals::Execute(void) { - CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread ); - CMICMDBASE_GETOPTION( pArgFrame, OptionLong, m_constStrArgFrame ); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if( pArgThread->GetFound() ) - { - if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) ); - return MIstatus::failure; - } - } - MIuint64 nFrame = UINT64_MAX; - if( pArgFrame->GetFound() ) - { - if( !pArgFrame->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nFrame ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str() ) ); - return MIstatus::failure; - } - } - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID( nThreadId ) : rProcess.GetSelectedThread(); - m_bThreadInvalid = !thread.IsValid(); - if( m_bThreadInvalid ) - return MIstatus::success; - - const lldb::StopReason eStopReason = thread.GetStopReason(); - if( (eStopReason == lldb::eStopReasonNone) || (eStopReason == lldb::eStopReasonInvalid) ) - { - m_bThreadInvalid = true; - return MIstatus::success; - } - - const MIuint nFrames = thread.GetNumFrames(); MIunused( nFrames ); - lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex( nFrame ) : thread.GetSelectedFrame(); - CMICmnMIValueList miValueList( true ); - const MIuint maskVarTypes = 0x0110; - if( !rSessionInfo.MIResponseFormVariableInfo( frame, maskVarTypes, miValueList ) ) - return MIstatus::failure; - - m_miValueList = miValueList; - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (pArgThread->GetFound()) + { + if (!pArgThread->GetExpectedOption(nThreadId)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); + return MIstatus::failure; + } + } + MIuint64 nFrame = UINT64_MAX; + if (pArgFrame->GetFound()) + { + if (!pArgFrame->GetExpectedOption(nFrame)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str())); + return MIstatus::failure; + } + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID(nThreadId) : rProcess.GetSelectedThread(); + m_bThreadInvalid = !thread.IsValid(); + if (m_bThreadInvalid) + return MIstatus::success; + + const lldb::StopReason eStopReason = thread.GetStopReason(); + if ((eStopReason == lldb::eStopReasonNone) || (eStopReason == lldb::eStopReasonInvalid)) + { + m_bThreadInvalid = true; + return MIstatus::success; + } + + const MIuint nFrames = thread.GetNumFrames(); + MIunused(nFrames); + lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame) : thread.GetSelectedFrame(); + CMICmnMIValueList miValueList(true); + const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Locals; + if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes, miValueList)) + return MIstatus::failure; + + m_miValueList = miValueList; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdStackListLocals::Acknowledge( void ) +bool +CMICmdCmdStackListLocals::Acknowledge(void) { - if( m_bThreadInvalid ) - { - // MI print "%s^done,locals=[]" - const CMICmnMIValueList miValueList( true ); - const CMICmnMIValueResult miValueResult( "locals", miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - // MI print "%s^done,locals=[%s]" - const CMICmnMIValueResult miValueResult( "locals", m_miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + if (m_bThreadInvalid) + { + // MI print "%s^done,locals=[]" + const CMICmnMIValueList miValueList(true); + const CMICmnMIValueResult miValueResult("locals", miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + // MI print "%s^done,locals=[%s]" + const CMICmnMIValueResult miValueResult("locals", m_miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdStackListLocals::CreateSelf( void ) +CMICmdBase * +CMICmdCmdStackListLocals::CreateSelf(void) { - return new CMICmdCmdStackListLocals(); + return new CMICmdCmdStackListLocals(); } - diff --git a/tools/lldb-mi/MICmdCmdStack.h b/tools/lldb-mi/MICmdCmdStack.h index 0c3a291d5870..bae43dceed6d 100644 --- a/tools/lldb-mi/MICmdCmdStack.h +++ b/tools/lldb-mi/MICmdCmdStack.h @@ -8,27 +8,27 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdStack.h +// File: MICmdCmdStack.h // -// Overview: CMICmdCmdStackInfoDepth interface. -// CMICmdCmdStackListFrames interface. -// CMICmdCmdStackListArguments interface. -// CMICmdCmdStackListLocals interface. +// Overview: CMICmdCmdStackInfoDepth interface. +// CMICmdCmdStackListFrames interface. +// CMICmdCmdStackListArguments interface. +// CMICmdCmdStackListLocals interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -38,147 +38,146 @@ #include "MICmnMIValueList.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "stack-info-depth". -// Gotchas: None. -// Authors: Illya Rudkin 21/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "stack-info-depth". +// Gotchas: None. +// Authors: Illya Rudkin 21/03/2014. +// Changes: None. //-- class CMICmdCmdStackInfoDepth : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdStackInfoDepth( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdStackInfoDepth( void ); - -// Attributes: -private: - MIuint m_nThreadFrames; - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgMaxDepth; // Not handled by *this command + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdStackInfoDepth(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdStackInfoDepth(void); + + // Attributes: + private: + MIuint m_nThreadFrames; + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgMaxDepth; // Not handled by *this command }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "stack-list-frames". -// Gotchas: None. -// Authors: Illya Rudkin 21/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "stack-list-frames". +// Gotchas: None. +// Authors: Illya Rudkin 21/03/2014. +// Changes: None. //-- class CMICmdCmdStackListFrames : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdStackListFrames( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdStackListFrames( void ); - -// Typedefs: -private: - typedef std::vector< CMICmnMIValueResult > VecMIValueResult_t; - -// Attributes: -private: - MIuint m_nThreadFrames; - VecMIValueResult_t m_vecMIValueResult; - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgFrameLow; - const CMIUtilString m_constStrArgFrameHigh; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdStackListFrames(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdStackListFrames(void); + + // Typedefs: + private: + typedef std::vector VecMIValueResult_t; + + // Attributes: + private: + MIuint m_nThreadFrames; + VecMIValueResult_t m_vecMIValueResult; + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgFrameLow; + const CMIUtilString m_constStrArgFrameHigh; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "stack-list-arguments". -// Gotchas: None. -// Authors: Illya Rudkin 24/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "stack-list-arguments". +// Gotchas: None. +// Authors: Illya Rudkin 24/03/2014. +// Changes: None. //-- class CMICmdCmdStackListArguments : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdStackListArguments( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdStackListArguments( void ); - -// Attributes: -private: - bool m_bThreadInvalid; // True = yes invalid thread, false = thread object valid - CMICmnMIValueList m_miValueList; - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdStackListArguments(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdStackListArguments(void); + + // Attributes: + private: + bool m_bThreadInvalid; // True = yes invalid thread, false = thread object valid + CMICmnMIValueList m_miValueList; + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "stack-list-locals". -// Gotchas: None. -// Authors: Illya Rudkin 24/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "stack-list-locals". +// Gotchas: None. +// Authors: Illya Rudkin 24/03/2014. +// Changes: None. //-- class CMICmdCmdStackListLocals : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdStackListLocals( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdStackListLocals( void ); - -// Attributes: -private: - bool m_bThreadInvalid; // True = yes invalid thread, false = thread object valid - CMICmnMIValueList m_miValueList; - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdStackListLocals(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdStackListLocals(void); + + // Attributes: + private: + bool m_bThreadInvalid; // True = yes invalid thread, false = thread object valid + CMICmnMIValueList m_miValueList; + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command }; - diff --git a/tools/lldb-mi/MICmdCmdSupportInfo.cpp b/tools/lldb-mi/MICmdCmdSupportInfo.cpp index e6f96f094e58..c2fc572f8c17 100644 --- a/tools/lldb-mi/MICmdCmdSupportInfo.cpp +++ b/tools/lldb-mi/MICmdCmdSupportInfo.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdSupportListInfo.cpp +// File: MICmdCmdSupportListInfo.cpp // -// Overview: CMICmdCmdSupportInfoMiCmdQuery implementation. +// Overview: CMICmdCmdSupportInfoMiCmdQuery implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -28,102 +28,106 @@ #include "MICmdFactory.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdSupportInfoMiCmdQuery constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdSupportInfoMiCmdQuery constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdSupportInfoMiCmdQuery::CMICmdCmdSupportInfoMiCmdQuery( void ) -: m_bCmdFound( false ) -, m_constStrArgCmdName( "cmd_name" ) +CMICmdCmdSupportInfoMiCmdQuery::CMICmdCmdSupportInfoMiCmdQuery(void) + : m_bCmdFound(false) + , m_constStrArgCmdName("cmd_name") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "info-gdb-mi-command"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdSupportInfoMiCmdQuery::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "info-gdb-mi-command"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdSupportInfoMiCmdQuery::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdSupportInfoMiCmdQuery destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdSupportInfoMiCmdQuery destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdSupportInfoMiCmdQuery::~CMICmdCmdSupportInfoMiCmdQuery( void ) +CMICmdCmdSupportInfoMiCmdQuery::~CMICmdCmdSupportInfoMiCmdQuery(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdSupportInfoMiCmdQuery::ParseArgs( void ) +bool +CMICmdCmdSupportInfoMiCmdQuery::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgCmdName, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgCmdName, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdSupportInfoMiCmdQuery::Execute( void ) +bool +CMICmdCmdSupportInfoMiCmdQuery::Execute(void) { - CMICMDBASE_GETOPTION( pArgNamedCmdName, String, m_constStrArgCmdName ); - const CMIUtilString & rCmdToQuery( pArgNamedCmdName->GetValue() ); - const MIuint nLen = rCmdToQuery.length(); - const CMICmdFactory & rCmdFactory = CMICmdFactory::Instance(); - if( (nLen > 1) && (rCmdToQuery[ 0 ] == '-') ) - m_bCmdFound = rCmdFactory.CmdExist( rCmdToQuery.substr( 1, nLen - 1 ).c_str() ); - else - m_bCmdFound = rCmdFactory.CmdExist( rCmdToQuery ); - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgNamedCmdName, String, m_constStrArgCmdName); + const CMIUtilString &rCmdToQuery(pArgNamedCmdName->GetValue()); + const MIuint nLen = rCmdToQuery.length(); + const CMICmdFactory &rCmdFactory = CMICmdFactory::Instance(); + if ((nLen > 1) && (rCmdToQuery[0] == '-')) + m_bCmdFound = rCmdFactory.CmdExist(rCmdToQuery.substr(1, nLen - 1).c_str()); + else + m_bCmdFound = rCmdFactory.CmdExist(rCmdToQuery); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdSupportInfoMiCmdQuery::Acknowledge( void ) +bool +CMICmdCmdSupportInfoMiCmdQuery::Acknowledge(void) { - const CMICmnMIValueConst miValueConst( m_bCmdFound ? "true" : "false" ); - const CMICmnMIValueResult miValueResult( "exists", miValueConst ); - const CMICmnMIValueTuple miValueTuple( miValueResult ); - const CMICmnMIValueResult miValueResult2( "command", miValueTuple ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult2 ); - m_miResultRecord = miRecordResult; + const CMICmnMIValueConst miValueConst(m_bCmdFound ? "true" : "false"); + const CMICmnMIValueResult miValueResult("exists", miValueConst); + const CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueResult miValueResult2("command", miValueTuple); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult2); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdSupportInfoMiCmdQuery::CreateSelf( void ) +CMICmdBase * +CMICmdCmdSupportInfoMiCmdQuery::CreateSelf(void) { - return new CMICmdCmdSupportInfoMiCmdQuery(); + return new CMICmdCmdSupportInfoMiCmdQuery(); } diff --git a/tools/lldb-mi/MICmdCmdSupportInfo.h b/tools/lldb-mi/MICmdCmdSupportInfo.h index 2633e99ce10e..b643d4af1aa4 100644 --- a/tools/lldb-mi/MICmdCmdSupportInfo.h +++ b/tools/lldb-mi/MICmdCmdSupportInfo.h @@ -8,24 +8,24 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdSupportInfo.h +// File: MICmdCmdSupportInfo.h // -// Overview: CMICmdCmdSupportInfoMiCmdQuery interface. +// Overview: CMICmdCmdSupportInfoMiCmdQuery interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -34,36 +34,35 @@ #include "MICmdBase.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "info-gdb-mi-command". -// This command does not follow the MI documentation exactly. -// Gotchas: None. -// Authors: Illya Rudkin 06/05/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "info-gdb-mi-command". +// This command does not follow the MI documentation exactly. +// Gotchas: None. +// Authors: Illya Rudkin 06/05/2014. +// Changes: None. //-- class CMICmdCmdSupportInfoMiCmdQuery : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdSupportInfoMiCmdQuery( void ); + // Methods: + public: + /* ctor */ CMICmdCmdSupportInfoMiCmdQuery(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdSupportInfoMiCmdQuery( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdSupportInfoMiCmdQuery(void); -// Attributes: -private: - bool m_bCmdFound; // True = query for the command in command factory found, false = not found not recognised - const CMIUtilString m_constStrArgCmdName; + // Attributes: + private: + bool m_bCmdFound; // True = query for the command in command factory found, false = not found not recognised + const CMIUtilString m_constStrArgCmdName; }; - diff --git a/tools/lldb-mi/MICmdCmdSupportList.cpp b/tools/lldb-mi/MICmdCmdSupportList.cpp index 2e4beb3edc85..02728b95feb0 100644 --- a/tools/lldb-mi/MICmdCmdSupportList.cpp +++ b/tools/lldb-mi/MICmdCmdSupportList.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdSupportList.cpp +// File: MICmdCmdSupportList.cpp // -// Overview: CMICmdCmdSupportListFeatures implementation. +// Overview: CMICmdCmdSupportListFeatures implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -26,77 +26,80 @@ #include "MICmnMIValueList.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdSupportListFeatures constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdSupportListFeatures constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdSupportListFeatures::CMICmdCmdSupportListFeatures( void ) +CMICmdCmdSupportListFeatures::CMICmdCmdSupportListFeatures(void) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "list-features"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdSupportListFeatures::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "list-features"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdSupportListFeatures::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdSupportListFeatures destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdSupportListFeatures destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdSupportListFeatures::~CMICmdCmdSupportListFeatures( void ) +CMICmdCmdSupportListFeatures::~CMICmdCmdSupportListFeatures(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdSupportListFeatures::Execute( void ) +bool +CMICmdCmdSupportListFeatures::Execute(void) { - // Do nothing - - return MIstatus::success; + // Do nothing + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdSupportListFeatures::Acknowledge( void ) +bool +CMICmdCmdSupportListFeatures::Acknowledge(void) { - const CMICmnMIValueConst miValueConst( "data-read-memory-bytes" ); - const CMICmnMIValueList miValueList( miValueConst ); - const CMICmnMIValueResult miValueResult( "features", miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; + const CMICmnMIValueConst miValueConst("data-read-memory-bytes"); + const CMICmnMIValueList miValueList(miValueConst); + const CMICmnMIValueResult miValueResult("features", miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdSupportListFeatures::CreateSelf( void ) +CMICmdBase * +CMICmdCmdSupportListFeatures::CreateSelf(void) { - return new CMICmdCmdSupportListFeatures(); + return new CMICmdCmdSupportListFeatures(); } diff --git a/tools/lldb-mi/MICmdCmdSupportList.h b/tools/lldb-mi/MICmdCmdSupportList.h index d9909a88997f..24267579d676 100644 --- a/tools/lldb-mi/MICmdCmdSupportList.h +++ b/tools/lldb-mi/MICmdCmdSupportList.h @@ -8,24 +8,24 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdSupportList.h +// File: MICmdCmdSupportList.h // -// Overview: CMICmdCmdSupportListFeatures interface. +// Overview: CMICmdCmdSupportListFeatures interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -34,30 +34,29 @@ #include "MICmdBase.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "list-features". -// This command does not follow the MI documentation exactly. -// Gotchas: None. -// Authors: Illya Rudkin 03/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "list-features". +// This command does not follow the MI documentation exactly. +// Gotchas: None. +// Authors: Illya Rudkin 03/03/2014. +// Changes: None. //-- class CMICmdCmdSupportListFeatures : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdSupportListFeatures( void ); + // Methods: + public: + /* ctor */ CMICmdCmdSupportListFeatures(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdSupportListFeatures( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdSupportListFeatures(void); }; - diff --git a/tools/lldb-mi/MICmdCmdTarget.cpp b/tools/lldb-mi/MICmdCmdTarget.cpp index 60c1c5e4bba2..ec19493af33b 100644 --- a/tools/lldb-mi/MICmdCmdTarget.cpp +++ b/tools/lldb-mi/MICmdCmdTarget.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdTarget.cpp +// File: MICmdCmdTarget.cpp // -// Overview: CMICmdCmdTargetSelect implementation. +// Overview: CMICmdCmdTargetSelect implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third Party Headers: @@ -34,184 +34,188 @@ #include "MICmdArgValString.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdTargetSelect constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdTargetSelect constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdTargetSelect::CMICmdCmdTargetSelect( void ) -: m_constStrArgNamedType( "type" ) -, m_constStrArgNamedParameters( "parameters" ) +CMICmdCmdTargetSelect::CMICmdCmdTargetSelect(void) + : m_constStrArgNamedType("type") + , m_constStrArgNamedParameters("parameters") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "target-select"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdTargetSelect::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "target-select"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdTargetSelect::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdTargetSelect destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdTargetSelect destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdTargetSelect::~CMICmdCmdTargetSelect( void ) +CMICmdCmdTargetSelect::~CMICmdCmdTargetSelect(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdTargetSelect::ParseArgs( void ) +bool +CMICmdCmdTargetSelect::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedType, true, true )) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedParameters, true, true )) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedType, true, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedParameters, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Synopsis: -target-select type parameters ... -// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Synopsis: -target-select type parameters ... +// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdTargetSelect::Execute( void ) +bool +CMICmdCmdTargetSelect::Execute(void) { - CMICMDBASE_GETOPTION( pArgType, String, m_constStrArgNamedType ); - CMICMDBASE_GETOPTION( pArgParameters, String, m_constStrArgNamedParameters ); - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - - // Check we have a valid target - // Note: target created via 'file-exec-and-symbols' command - if( !rSessionInfo.m_lldbTarget.IsValid() ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_TARGET_CURRENT ), m_cmdData.strMiCmd.c_str() ) ); - return MIstatus::failure; - } - - // Verify that we are executing remotely - const CMIUtilString & rRemoteType( pArgType->GetValue() ); - if( rRemoteType != "remote" ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_TARGET_TYPE ), m_cmdData.strMiCmd.c_str(), rRemoteType.c_str() ) ); - return MIstatus::failure; - } - - // Create a URL pointing to the remote gdb stub - const CMIUtilString strUrl = CMIUtilString::Format( "connect://%s", pArgParameters->GetValue().c_str() ); - - // Ask LLDB to collect to the target port - const MIchar * pPlugin( "gdb-remote" ); - lldb::SBError error; - lldb::SBProcess process = rSessionInfo.m_lldbTarget.ConnectRemote( rSessionInfo.m_rLlldbListener, strUrl.c_str(), pPlugin, error ); - - // Verify that we have managed to connect successfully - lldb::SBStream errMsg; - if( !process.IsValid() ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_TARGET_PLUGIN ), m_cmdData.strMiCmd.c_str(), errMsg.GetData() ) ); - return MIstatus::failure; - } - if( error.Fail() ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_CONNECT_TO_TARGET ), m_cmdData.strMiCmd.c_str(), errMsg.GetData() ) ); - return MIstatus::failure; - } - - // Save the process in the session info - // Note: Order is important here since this process handle may be used by CMICmnLLDBDebugHandleEvents - // which can fire when interpreting via HandleCommand() below. - rSessionInfo.m_lldbProcess = process; - - // Set the environment path if we were given one - CMIUtilString strWkDir; - if( rSessionInfo.SharedDataRetrieve< CMIUtilString >( rSessionInfo.m_constStrSharedDataKeyWkDir, strWkDir ) ) - { - lldb::SBDebugger & rDbgr = rSessionInfo.m_rLldbDebugger; - if( !rDbgr.SetCurrentPlatformSDKRoot( strWkDir.c_str() ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_FNFAILED ), m_cmdData.strMiCmd.c_str(), "target-select" ) ); - return MIstatus::failure; - } - } - - // Set the shared object path if we were given one - CMIUtilString strSolibPath; - if( rSessionInfo.SharedDataRetrieve< CMIUtilString >( rSessionInfo.m_constStrSharedDataSolibPath, strSolibPath ) ) - { - lldb::SBDebugger & rDbgr = rSessionInfo.m_rLldbDebugger; - lldb::SBCommandInterpreter cmdIterpreter = rDbgr.GetCommandInterpreter(); - - CMIUtilString strCmdString = CMIUtilString::Format( "target modules search-paths add . %s", strSolibPath.c_str() ); - - lldb::SBCommandReturnObject retObj; - cmdIterpreter.HandleCommand( strCmdString.c_str(), retObj, false ); - - if( !retObj.Succeeded() ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_FNFAILED ), m_cmdData.strMiCmd.c_str(), "target-select" ) ); - return MIstatus::failure; - } - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgType, String, m_constStrArgNamedType); + CMICMDBASE_GETOPTION(pArgParameters, String, m_constStrArgNamedParameters); + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + + // Check we have a valid target + // Note: target created via 'file-exec-and-symbols' command + if (!rSessionInfo.m_lldbTarget.IsValid()) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT), m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + // Verify that we are executing remotely + const CMIUtilString &rRemoteType(pArgType->GetValue()); + if (rRemoteType != "remote") + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_TYPE), m_cmdData.strMiCmd.c_str(), rRemoteType.c_str())); + return MIstatus::failure; + } + + // Create a URL pointing to the remote gdb stub + const CMIUtilString strUrl = CMIUtilString::Format("connect://%s", pArgParameters->GetValue().c_str()); + + // Ask LLDB to collect to the target port + const MIchar *pPlugin("gdb-remote"); + lldb::SBError error; + lldb::SBProcess process = rSessionInfo.m_lldbTarget.ConnectRemote(rSessionInfo.m_rLlldbListener, strUrl.c_str(), pPlugin, error); + + // Verify that we have managed to connect successfully + lldb::SBStream errMsg; + if (!process.IsValid()) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_PLUGIN), m_cmdData.strMiCmd.c_str(), errMsg.GetData())); + return MIstatus::failure; + } + if (error.Fail()) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_CONNECT_TO_TARGET), m_cmdData.strMiCmd.c_str(), errMsg.GetData())); + return MIstatus::failure; + } + + // Save the process in the session info + // Note: Order is important here since this process handle may be used by CMICmnLLDBDebugHandleEvents + // which can fire when interpreting via HandleCommand() below. + rSessionInfo.m_lldbProcess = process; + + // Set the environment path if we were given one + CMIUtilString strWkDir; + if (rSessionInfo.SharedDataRetrieve(rSessionInfo.m_constStrSharedDataKeyWkDir, strWkDir)) + { + lldb::SBDebugger &rDbgr = rSessionInfo.m_rLldbDebugger; + if (!rDbgr.SetCurrentPlatformSDKRoot(strWkDir.c_str())) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), m_cmdData.strMiCmd.c_str(), "target-select")); + return MIstatus::failure; + } + } + + // Set the shared object path if we were given one + CMIUtilString strSolibPath; + if (rSessionInfo.SharedDataRetrieve(rSessionInfo.m_constStrSharedDataSolibPath, strSolibPath)) + { + lldb::SBDebugger &rDbgr = rSessionInfo.m_rLldbDebugger; + lldb::SBCommandInterpreter cmdIterpreter = rDbgr.GetCommandInterpreter(); + + CMIUtilString strCmdString = CMIUtilString::Format("target modules search-paths add . %s", strSolibPath.c_str()); + + lldb::SBCommandReturnObject retObj; + cmdIterpreter.HandleCommand(strCmdString.c_str(), retObj, false); + + if (!retObj.Succeeded()) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), m_cmdData.strMiCmd.c_str(), "target-select")); + return MIstatus::failure; + } + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdTargetSelect::Acknowledge( void ) +bool +CMICmdCmdTargetSelect::Acknowledge(void) { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Connected ); - m_miResultRecord = miRecordResult; - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID(); - // Prod the client i.e. Eclipse with out-of-band results to help it 'continue' because it is using LLDB debugger - // Give the client '=thread-group-started,id="i1"' - m_bHasResultRecordExtra = true; - const CMICmnMIValueConst miValueConst2( "i1" ); - const CMICmnMIValueResult miValueResult2( "id", miValueConst2 ); - const CMIUtilString strPid( CMIUtilString::Format( "%lld", pid ) ); - const CMICmnMIValueConst miValueConst( strPid ); - const CMICmnMIValueResult miValueResult( "pid", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2 ); - miOutOfBand.Add( miValueResult ); - m_miResultRecordExtra = miOutOfBand.GetString(); - - return MIstatus::success; + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Connected); + m_miResultRecord = miRecordResult; + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID(); + // Prod the client i.e. Eclipse with out-of-band results to help it 'continue' because it is using LLDB debugger + // Give the client '=thread-group-started,id="i1"' + m_bHasResultRecordExtra = true; + const CMICmnMIValueConst miValueConst2("i1"); + const CMICmnMIValueResult miValueResult2("id", miValueConst2); + const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); + const CMICmnMIValueConst miValueConst(strPid); + const CMICmnMIValueResult miValueResult("pid", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2); + miOutOfBand.Add(miValueResult); + m_miResultRecordExtra = miOutOfBand.GetString(); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdTargetSelect::CreateSelf( void ) +CMICmdBase * +CMICmdCmdTargetSelect::CreateSelf(void) { - return new CMICmdCmdTargetSelect(); + return new CMICmdCmdTargetSelect(); } diff --git a/tools/lldb-mi/MICmdCmdTarget.h b/tools/lldb-mi/MICmdCmdTarget.h index f904f20ee4f6..0ed790f01e02 100644 --- a/tools/lldb-mi/MICmdCmdTarget.h +++ b/tools/lldb-mi/MICmdCmdTarget.h @@ -8,24 +8,24 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdTarget.h +// File: MICmdCmdTarget.h // -// Overview: CMICmdCmdTargetSelect interface. +// Overview: CMICmdCmdTargetSelect interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -36,35 +36,35 @@ #include "MICmnMIValueList.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "target-select". -// http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation -// Gotchas: None. -// Authors: Illya Rudkin 05/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "target-select". +// http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation +// Gotchas: None. +// Authors: Illya Rudkin 05/03/2014. +// Changes: None. //-- class CMICmdCmdTargetSelect : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdTargetSelect( void ); + // Methods: + public: + /* ctor */ CMICmdCmdTargetSelect(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdTargetSelect( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdTargetSelect(void); -// Attributes: -private: - const CMIUtilString m_constStrArgNamedType; - const CMIUtilString m_constStrArgNamedParameters; + // Attributes: + private: + const CMIUtilString m_constStrArgNamedType; + const CMIUtilString m_constStrArgNamedParameters; }; diff --git a/tools/lldb-mi/MICmdCmdThread.cpp b/tools/lldb-mi/MICmdCmdThread.cpp index 8cfaae804931..3a448a777008 100644 --- a/tools/lldb-mi/MICmdCmdThread.cpp +++ b/tools/lldb-mi/MICmdCmdThread.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdThread.cpp +// File: MICmdCmdThread.cpp // -// Overview: CMICmdCmdThreadInfo implementation. +// Overview: CMICmdCmdThreadInfo implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third Party Headers: @@ -32,176 +32,180 @@ #include "MICmdArgValNumber.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdThreadInfo constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdThreadInfo constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdThreadInfo::CMICmdCmdThreadInfo( void ) -: m_bSingleThread( false ) -, m_bThreadInvalid( true ) -, m_constStrArgNamedThreadId( "thread-id" ) +CMICmdCmdThreadInfo::CMICmdCmdThreadInfo(void) + : m_bSingleThread(false) + , m_bThreadInvalid(true) + , m_constStrArgNamedThreadId("thread-id") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "thread-info"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdThreadInfo::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "thread-info"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdThreadInfo::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdThreadInfo destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdThreadInfo destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdThreadInfo::~CMICmdCmdThreadInfo( void ) +CMICmdCmdThreadInfo::~CMICmdCmdThreadInfo(void) { - m_vecMIValueTuple.clear(); + m_vecMIValueTuple.clear(); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdThreadInfo::ParseArgs( void ) +bool +CMICmdCmdThreadInfo::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNamedThreadId, false, true )) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNamedThreadId, false, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdThreadInfo::Execute( void ) +bool +CMICmdCmdThreadInfo::Execute(void) { - CMICMDBASE_GETOPTION( pArgThreadId, Number, m_constStrArgNamedThreadId ); - MIuint nThreadId = 0; - if( pArgThreadId->GetFound() && pArgThreadId->GetValid() ) - { - m_bSingleThread = true; - nThreadId = static_cast< MIuint >( pArgThreadId->GetValue() ); - } - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = rProcess.GetSelectedThread(); - - if( m_bSingleThread ) - { - thread = rProcess.GetThreadByIndexID( nThreadId ); - m_bThreadInvalid = thread.IsValid(); - if( !m_bThreadInvalid ) - return MIstatus::success; - - CMICmnMIValueTuple miTuple; - if( !rSessionInfo.MIResponseFormThreadInfo3( m_cmdData, thread, miTuple ) ) - return MIstatus::failure; - - m_miValueTupleThread = miTuple; - - return MIstatus::success; - } - - // Multiple threads - m_vecMIValueTuple.clear(); - const MIuint nThreads = rProcess.GetNumThreads(); - for( MIuint i = 0; i < nThreads; i++ ) - { - lldb::SBThread thread = rProcess.GetThreadAtIndex( i ); - if( thread.IsValid() ) - { - CMICmnMIValueTuple miTuple; - if( !rSessionInfo.MIResponseFormThreadInfo3( m_cmdData, thread, miTuple ) ) - return MIstatus::failure; - - m_vecMIValueTuple.push_back( miTuple ); - } - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgThreadId, Number, m_constStrArgNamedThreadId); + MIuint nThreadId = 0; + if (pArgThreadId->GetFound() && pArgThreadId->GetValid()) + { + m_bSingleThread = true; + nThreadId = static_cast(pArgThreadId->GetValue()); + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + lldb::SBThread thread = rProcess.GetSelectedThread(); + + if (m_bSingleThread) + { + thread = rProcess.GetThreadByIndexID(nThreadId); + m_bThreadInvalid = thread.IsValid(); + if (!m_bThreadInvalid) + return MIstatus::success; + + CMICmnMIValueTuple miTuple; + if (!rSessionInfo.MIResponseFormThreadInfo3(m_cmdData, thread, miTuple)) + return MIstatus::failure; + + m_miValueTupleThread = miTuple; + + return MIstatus::success; + } + + // Multiple threads + m_vecMIValueTuple.clear(); + const MIuint nThreads = rProcess.GetNumThreads(); + for (MIuint i = 0; i < nThreads; i++) + { + lldb::SBThread thread = rProcess.GetThreadAtIndex(i); + if (thread.IsValid()) + { + CMICmnMIValueTuple miTuple; + if (!rSessionInfo.MIResponseFormThreadInfo3(m_cmdData, thread, miTuple)) + return MIstatus::failure; + + m_vecMIValueTuple.push_back(miTuple); + } + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdThreadInfo::Acknowledge( void ) +bool +CMICmdCmdThreadInfo::Acknowledge(void) { - if( m_bSingleThread ) - { - if( !m_bThreadInvalid ) - { - const CMICmnMIValueConst miValueConst( "invalid thread id" ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - // MI print "%s^done,threads=[{id=\"%d\",target-id=\"%s\",frame={},state=\"%s\"}] - const CMICmnMIValueList miValueList( m_miValueTupleThread ); - const CMICmnMIValueResult miValueResult( "threads", miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - // Build up a list of thread information from tuples - VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin(); - if( it == m_vecMIValueTuple.end() ) - { - const CMICmnMIValueConst miValueConst( "[]" ); - const CMICmnMIValueResult miValueResult( "threads", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - CMICmnMIValueList miValueList( *it ); - ++it; - while( it != m_vecMIValueTuple.end() ) - { - const CMICmnMIValueTuple & rTuple( *it ); - miValueList.Add( rTuple ); - - // Next - ++it; - } - - const CMICmnMIValueResult miValueResult( "threads", miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + if (m_bSingleThread) + { + if (!m_bThreadInvalid) + { + const CMICmnMIValueConst miValueConst("invalid thread id"); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + // MI print "%s^done,threads=[{id=\"%d\",target-id=\"%s\",frame={},state=\"%s\"}] + const CMICmnMIValueList miValueList(m_miValueTupleThread); + const CMICmnMIValueResult miValueResult("threads", miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + // Build up a list of thread information from tuples + VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin(); + if (it == m_vecMIValueTuple.end()) + { + const CMICmnMIValueConst miValueConst("[]"); + const CMICmnMIValueResult miValueResult("threads", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + CMICmnMIValueList miValueList(*it); + ++it; + while (it != m_vecMIValueTuple.end()) + { + const CMICmnMIValueTuple &rTuple(*it); + miValueList.Add(rTuple); + + // Next + ++it; + } + + const CMICmnMIValueResult miValueResult("threads", miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdThreadInfo::CreateSelf( void ) +CMICmdBase * +CMICmdCmdThreadInfo::CreateSelf(void) { - return new CMICmdCmdThreadInfo(); + return new CMICmdCmdThreadInfo(); } diff --git a/tools/lldb-mi/MICmdCmdThread.h b/tools/lldb-mi/MICmdCmdThread.h index 33cd786a8cac..59b6b124cce1 100644 --- a/tools/lldb-mi/MICmdCmdThread.h +++ b/tools/lldb-mi/MICmdCmdThread.h @@ -8,24 +8,24 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdThread.h +// File: MICmdCmdThread.h // -// Overview: CMICmdCmdThreadInfo interface. +// Overview: CMICmdCmdThreadInfo interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -36,41 +36,41 @@ #include "MICmnMIValueList.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "thread-info". -// Gotchas: None. -// Authors: Illya Rudkin 07/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "thread-info". +// Gotchas: None. +// Authors: Illya Rudkin 07/03/2014. +// Changes: None. //-- class CMICmdCmdThreadInfo : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdThreadInfo( void ); + // Methods: + public: + /* ctor */ CMICmdCmdThreadInfo(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdThreadInfo( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdThreadInfo(void); -// Typedefs: -private: - typedef std::vector< CMICmnMIValueTuple > VecMIValueTuple_t; + // Typedefs: + private: + typedef std::vector VecMIValueTuple_t; -// Attributes: -private: - CMICmnMIValueTuple m_miValueTupleThread; - bool m_bSingleThread; // True = yes single thread, false = multiple threads - bool m_bThreadInvalid; // True = invalid, false = ok - VecMIValueTuple_t m_vecMIValueTuple; - const CMIUtilString m_constStrArgNamedThreadId; + // Attributes: + private: + CMICmnMIValueTuple m_miValueTupleThread; + bool m_bSingleThread; // True = yes single thread, false = multiple threads + bool m_bThreadInvalid; // True = invalid, false = ok + VecMIValueTuple_t m_vecMIValueTuple; + const CMIUtilString m_constStrArgNamedThreadId; }; diff --git a/tools/lldb-mi/MICmdCmdTrace.cpp b/tools/lldb-mi/MICmdCmdTrace.cpp index 8623db9eb151..4ee72d300cc4 100644 --- a/tools/lldb-mi/MICmdCmdTrace.cpp +++ b/tools/lldb-mi/MICmdCmdTrace.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdTrace.cpp +// File: MICmdCmdTrace.cpp // -// Overview: CMICmdCmdTraceStatus implementation. +// Overview: CMICmdCmdTraceStatus implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -25,75 +25,78 @@ #include "MICmnMIValueConst.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdTraceStatus constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdTraceStatus constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdTraceStatus::CMICmdCmdTraceStatus( void ) +CMICmdCmdTraceStatus::CMICmdCmdTraceStatus(void) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "trace-status"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdTraceStatus::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "trace-status"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdTraceStatus::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdTraceStatus destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdTraceStatus destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdTraceStatus::~CMICmdCmdTraceStatus( void ) +CMICmdCmdTraceStatus::~CMICmdCmdTraceStatus(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdTraceStatus::Execute( void ) +bool +CMICmdCmdTraceStatus::Execute(void) { - // Do nothing - return MIstatus::success; + // Do nothing + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdTraceStatus::Acknowledge( void ) +bool +CMICmdCmdTraceStatus::Acknowledge(void) { - const CMICmnMIValueConst miValueConst( MIRSRC( IDS_CMD_ERR_NOT_IMPLEMENTED ) ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + const CMICmnMIValueConst miValueConst(MIRSRC(IDS_CMD_ERR_NOT_IMPLEMENTED)); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdTraceStatus::CreateSelf( void ) +CMICmdBase * +CMICmdCmdTraceStatus::CreateSelf(void) { - return new CMICmdCmdTraceStatus(); + return new CMICmdCmdTraceStatus(); } diff --git a/tools/lldb-mi/MICmdCmdTrace.h b/tools/lldb-mi/MICmdCmdTrace.h index 2192d007a599..efe8e50b5c98 100644 --- a/tools/lldb-mi/MICmdCmdTrace.h +++ b/tools/lldb-mi/MICmdCmdTrace.h @@ -8,24 +8,24 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdTrace.h +// File: MICmdCmdTrace.h // -// Overview: CMICmdCmdTraceStatus interface. +// Overview: CMICmdCmdTraceStatus interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -34,28 +34,28 @@ #include "MICmdBase.h" //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "trace-status". -// Gotchas: None. -// Authors: Illya Rudkin 07/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "trace-status". +// Gotchas: None. +// Authors: Illya Rudkin 07/03/2014. +// Changes: None. //-- class CMICmdCmdTraceStatus : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); -// Methods: -public: - /* ctor */ CMICmdCmdTraceStatus( void ); + // Methods: + public: + /* ctor */ CMICmdCmdTraceStatus(void); -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdTraceStatus( void ); + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdTraceStatus(void); }; diff --git a/tools/lldb-mi/MICmdCmdVar.cpp b/tools/lldb-mi/MICmdCmdVar.cpp index 346d69600760..4aa4c2ae97cf 100644 --- a/tools/lldb-mi/MICmdCmdVar.cpp +++ b/tools/lldb-mi/MICmdCmdVar.cpp @@ -8,23 +8,23 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdVar.cpp +// File: MICmdCmdVar.cpp // -// Overview: CMICmdCmdVarCreate implementation. -// CMICmdCmdVarUpdate implementation. -// CMICmdCmdVarDelete implementation. -// CMICmdCmdVarAssign implementation. -// CMICmdCmdVarSetFormat implementation. -// CMICmdCmdVarListChildren implementation. -// CMICmdCmdVarEvaluateExpression implementation. -// CMICmdCmdVarInfoPathExpression implementation. -// CMICmdCmdVarShowAttributes implementation. +// Overview: CMICmdCmdVarCreate implementation. +// CMICmdCmdVarUpdate implementation. +// CMICmdCmdVarDelete implementation. +// CMICmdCmdVarAssign implementation. +// CMICmdCmdVarSetFormat implementation. +// CMICmdCmdVarListChildren implementation. +// CMICmdCmdVarEvaluateExpression implementation. +// CMICmdCmdVarInfoPathExpression implementation. +// CMICmdCmdVarShowAttributes implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third Party Headers: @@ -47,198 +47,205 @@ #include "MICmnLLDBUtilSBValue.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarCreate constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarCreate constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarCreate::CMICmdCmdVarCreate( void ) -: m_nChildren( 0 ) -, m_nMore( 0 ) -, m_nThreadId( 0 ) -, m_strType( "??" ) -, m_bValid( false ) -, m_strValue( "??" ) -, m_constStrArgThread( "thread" ) -, m_constStrArgThreadGroup( "thread-group" ) -, m_constStrArgFrame( "frame" ) -, m_constStrArgName( "name" ) -, m_constStrArgFrameAddr( "frame-addr" ) -, m_constStrArgExpression( "expression" ) +CMICmdCmdVarCreate::CMICmdCmdVarCreate(void) + : m_nChildren(0) + , m_nThreadId(0) + , m_strType("??") + , m_bValid(false) + , m_strValue("??") + , m_constStrArgThread("thread") + , m_constStrArgThreadGroup("thread-group") + , m_constStrArgFrame("frame") + , m_constStrArgName("name") + , m_constStrArgFrameAddr("frame-addr") + , m_constStrArgExpression("expression") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-create"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarCreate::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-create"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarCreate::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarCreate destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarCreate destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarCreate::~CMICmdCmdVarCreate( void ) +CMICmdCmdVarCreate::~CMICmdCmdVarCreate(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarCreate::ParseArgs( void ) +bool +CMICmdCmdVarCreate::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThreadGroup, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgFrame, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, false, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgFrameAddr, false, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgExpression, true, true, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && + m_setCmdArgs.Add( + *(new CMICmdArgValOptionLong(m_constStrArgThreadGroup, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); + bOk = bOk && + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgFrame, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, false, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgFrameAddr, false, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgExpression, true, true, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarCreate::Execute( void ) +bool +CMICmdCmdVarCreate::Execute(void) { - CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread ); - CMICMDBASE_GETOPTION( pArgFrame, OptionLong, m_constStrArgFrame ); - CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName ); - CMICMDBASE_GETOPTION( pArgFrameAddr, String, m_constStrArgFrameAddr ); - CMICMDBASE_GETOPTION( pArgExpression, String, m_constStrArgExpression ); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) ); - return MIstatus::failure; - } - m_nThreadId = nThreadId; - - // Retrieve the --frame option's number - MIuint64 nFrame = UINT64_MAX; - if( !pArgFrame->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nFrame ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str() ) ); - return MIstatus::failure; - } - - const CMICmdArgValOptionLong::VecArgObjPtr_t & rVecFrameId( pArgFrame->GetExpectedOptions() ); - CMICmdArgValOptionLong::VecArgObjPtr_t::const_iterator it2 = rVecFrameId.begin(); - if( it2 != rVecFrameId.end() ) - { - const CMICmdArgValNumber * pOption = static_cast< CMICmdArgValNumber * >( *it2 ); - nFrame = pOption->GetValue(); - } - - bool bAutoName = false; - const CMIUtilString strArgName; - if( pArgName->GetFound() ) - { - const CMIUtilString & rArg = pArgName->GetValue(); - bAutoName = (rArg == "-"); - } - - const CMIUtilString & rStrExpression( pArgExpression->GetValue() ); - m_strExpression = rStrExpression; - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - m_strVarName = ""; - if( bAutoName ) - { - m_strVarName = CMIUtilString::Format( "var%u", CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet() ); - CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc(); - } - lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = rProcess.GetThreadByIndexID( nThreadId ); - lldb::SBFrame frame = thread.GetFrameAtIndex( nFrame ); - lldb::SBValue value = frame.FindVariable( rStrExpression.c_str() ); - if( !value.IsValid() ) - value = frame.EvaluateExpression( rStrExpression.c_str() ); - if( value.IsValid() ) - { - m_bValid = true; - m_nChildren = value.GetNumChildren(); - m_strType = CMICmnLLDBUtilSBValue( value ).GetTypeNameDisplay(); - - // This gets added to CMICmnLLDBDebugSessionInfoVarObj static container of varObjs - CMICmnLLDBDebugSessionInfoVarObj varObj( rStrExpression, m_strVarName, value ); - m_strValue = varObj.GetValueFormatted(); - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame); + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + CMICMDBASE_GETOPTION(pArgFrameAddr, String, m_constStrArgFrameAddr); + CMICMDBASE_GETOPTION(pArgExpression, String, m_constStrArgExpression); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (!pArgThread->GetExpectedOption(nThreadId)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); + return MIstatus::failure; + } + m_nThreadId = nThreadId; + + // Retrieve the --frame option's number + MIuint64 nFrame = UINT64_MAX; + if (!pArgFrame->GetExpectedOption(nFrame)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str())); + return MIstatus::failure; + } + + const CMICmdArgValOptionLong::VecArgObjPtr_t &rVecFrameId(pArgFrame->GetExpectedOptions()); + CMICmdArgValOptionLong::VecArgObjPtr_t::const_iterator it2 = rVecFrameId.begin(); + if (it2 != rVecFrameId.end()) + { + const CMICmdArgValNumber *pOption = static_cast(*it2); + nFrame = pOption->GetValue(); + } + + bool bAutoName = false; + const CMIUtilString strArgName; + if (pArgName->GetFound()) + { + const CMIUtilString &rArg = pArgName->GetValue(); + bAutoName = (rArg == "-"); + } + + const CMIUtilString &rStrExpression(pArgExpression->GetValue()); + m_strExpression = rStrExpression; + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + m_strVarName = ""; + if (bAutoName) + { + m_strVarName = CMIUtilString::Format("var%u", CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet()); + CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc(); + } + lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + lldb::SBThread thread = rProcess.GetThreadByIndexID(nThreadId); + lldb::SBFrame frame = thread.GetFrameAtIndex(nFrame); + lldb::SBValue value = frame.FindVariable(rStrExpression.c_str()); + if (!value.IsValid()) + value = frame.EvaluateExpression(rStrExpression.c_str()); + if (value.IsValid()) + { + m_bValid = true; + m_nChildren = value.GetNumChildren(); + m_strType = CMICmnLLDBUtilSBValue(value).GetTypeNameDisplay(); + + // This gets added to CMICmnLLDBDebugSessionInfoVarObj static container of varObjs + CMICmnLLDBDebugSessionInfoVarObj varObj(rStrExpression, m_strVarName, value); + m_strValue = varObj.GetValueFormatted(); + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarCreate::Acknowledge( void ) +bool +CMICmdCmdVarCreate::Acknowledge(void) { - if( m_bValid ) - { - // MI print "%s^done,name=\"%s\",numchild=\"%d\",value=\"%s\",type=\"%s\",thread-id=\"%llu\",has_more=\"%u\"" - const CMICmnMIValueConst miValueConst( m_strVarName ); - CMICmnMIValueResult miValueResultAll( "name", miValueConst ); - const CMIUtilString strNumChild( CMIUtilString::Format( "%d", m_nChildren ) ); - const CMICmnMIValueConst miValueConst2( strNumChild ); - miValueResultAll.Add( "numchild", miValueConst2 ); - const CMICmnMIValueConst miValueConst3( m_strValue ); - miValueResultAll.Add( "value", miValueConst3 ); - const CMICmnMIValueConst miValueConst4( m_strType ); - miValueResultAll.Add( "type", miValueConst4 ); - const CMIUtilString strThreadId( CMIUtilString::Format( "%llu", m_nThreadId ) ); - const CMICmnMIValueConst miValueConst5( strThreadId ); - miValueResultAll.Add( "thread-id", miValueConst5 ); - const CMICmnMIValueConst miValueConst6( "0" ); - miValueResultAll.Add( "has_more", miValueConst6 ); - - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResultAll ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; - } - - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_CREATION_FAILED ), m_strExpression.c_str() ) ); - CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + if (m_bValid) + { + // MI print "%s^done,name=\"%s\",numchild=\"%d\",value=\"%s\",type=\"%s\",thread-id=\"%llu\",has_more=\"%u\"" + const CMICmnMIValueConst miValueConst(m_strVarName); + CMICmnMIValueResult miValueResultAll("name", miValueConst); + const CMIUtilString strNumChild(CMIUtilString::Format("%d", m_nChildren)); + const CMICmnMIValueConst miValueConst2(strNumChild); + miValueResultAll.Add("numchild", miValueConst2); + const CMICmnMIValueConst miValueConst3(m_strValue); + miValueResultAll.Add("value", miValueConst3); + const CMICmnMIValueConst miValueConst4(m_strType); + miValueResultAll.Add("type", miValueConst4); + const CMIUtilString strThreadId(CMIUtilString::Format("%llu", m_nThreadId)); + const CMICmnMIValueConst miValueConst5(strThreadId); + miValueResultAll.Add("thread-id", miValueConst5); + const CMICmnMIValueConst miValueConst6("0"); + miValueResultAll.Add("has_more", miValueConst6); + + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResultAll); + m_miResultRecord = miRecordResult; + + return MIstatus::success; + } + + const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_CREATION_FAILED), m_strExpression.c_str())); + CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdVarCreate::CreateSelf( void ) +CMICmdBase * +CMICmdCmdVarCreate::CreateSelf(void) { - return new CMICmdCmdVarCreate(); + return new CMICmdCmdVarCreate(); } //--------------------------------------------------------------------------------------- @@ -246,315 +253,324 @@ CMICmdBase * CMICmdCmdVarCreate::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarUpdate constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarUpdate constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarUpdate::CMICmdCmdVarUpdate( void ) -: m_constStrArgPrintValues( "print-values" ) -, m_constStrArgName( "name" ) -, m_bValueChangedArrayType( false ) -, m_bValueChangedCompositeType( false ) -, m_bValueChangedNormalType( false ) -, m_miValueList( true ) +CMICmdCmdVarUpdate::CMICmdCmdVarUpdate(void) + : m_constStrArgPrintValues("print-values") + , m_constStrArgName("name") + , m_bValueChangedArrayType(false) + , m_bValueChangedCompositeType(false) + , m_bValueChangedNormalType(false) + , m_miValueList(true) { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-update"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarUpdate::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-update"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarUpdate::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarUpdate destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarUpdate destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarUpdate::~CMICmdCmdVarUpdate( void ) +CMICmdCmdVarUpdate::~CMICmdCmdVarUpdate(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarUpdate::ParseArgs( void ) +bool +CMICmdCmdVarUpdate::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgPrintValues, false, false ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgPrintValues, false, false))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarUpdate::Execute( void ) +bool +CMICmdCmdVarUpdate::Execute(void) { - CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName ); - - const CMIUtilString & rVarObjName( pArgName->GetValue() ); - CMICmnLLDBDebugSessionInfoVarObj varObj; - if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) ); - return MIstatus::failure; - } - - const CMIUtilString & rVarRealName( varObj.GetNameReal() ); MIunused( rVarRealName ); - lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() ); - const bool bValid = rValue.IsValid(); - if( bValid && rValue.GetValueDidChange() ) - { - m_bValueChangedNormalType = true; - varObj.UpdateValue(); - m_strValueName = rVarObjName; - return MIstatus::success; - } - - // Examine an array type variable - if( !ExamineSBValueForChange( varObj, false, m_bValueChangedArrayType ) ) - return MIstatus::failure; - - // Handle composite types i.e. struct or arrays - const MIuint nChildren = rValue.GetNumChildren(); - for( MIuint i = 0; i < nChildren; i++ ) - { - lldb::SBValue member = rValue.GetChildAtIndex( i ); - if( !member.IsValid() ) - continue; - - const CMIUtilString varName( CMIUtilString::Format( "%s.%s", rVarObjName.c_str(), member.GetName() ) ); - if( member.GetValueDidChange() ) - { - // Handle composite - const CMIUtilString strValue( CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted( member, CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural ) ); - const CMIUtilString strInScope( member.IsInScope() ? "true" : "false" ); - MIFormResponse( varName, strValue, strInScope ); - - m_bValueChangedCompositeType = true; - } - else - { - // Handle array of composites - CMICmnLLDBDebugSessionInfoVarObj varObj; - if( CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( varName, varObj ) ) - { - bool bValueChanged = false; - if( ExamineSBValueForChange( varObj, true, bValueChanged ) ) - { - if( bValueChanged && CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( varName, varObj ) ) - { - lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() ); - const bool bValid = rValue.IsValid(); - const CMIUtilString strValue( bValid ? varObj.GetValueFormatted() : "" ); - const CMIUtilString strInScope( (bValid && rValue.IsInScope()) ? "true" : "false" ); - MIFormResponse( varName, strValue, strInScope ); - - m_bValueChangedCompositeType = true; - } - } - else - return MIstatus::failure; - } - } - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + + const CMIUtilString &rVarObjName(pArgName->GetValue()); + CMICmnLLDBDebugSessionInfoVarObj varObj; + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); + return MIstatus::failure; + } + + const CMIUtilString &rVarRealName(varObj.GetNameReal()); + MIunused(rVarRealName); + lldb::SBValue &rValue = const_cast(varObj.GetValue()); + const bool bValid = rValue.IsValid(); + if (bValid && rValue.GetValueDidChange()) + { + m_bValueChangedNormalType = true; + varObj.UpdateValue(); + m_strValueName = rVarObjName; + return MIstatus::success; + } + + // Examine an array type variable + if (!ExamineSBValueForChange(varObj, false, m_bValueChangedArrayType)) + return MIstatus::failure; + + // Handle composite types i.e. struct or arrays + const MIuint nChildren = rValue.GetNumChildren(); + for (MIuint i = 0; i < nChildren; i++) + { + lldb::SBValue member = rValue.GetChildAtIndex(i); + if (!member.IsValid()) + continue; + + const CMIUtilString varName(CMIUtilString::Format("%s.%s", rVarObjName.c_str(), member.GetName())); + if (member.GetValueDidChange()) + { + // Handle composite + const CMIUtilString strValue( + CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(member, CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural)); + const CMIUtilString strInScope(member.IsInScope() ? "true" : "false"); + MIFormResponse(varName, strValue, strInScope); + + m_bValueChangedCompositeType = true; + } + else + { + // Handle array of composites + CMICmnLLDBDebugSessionInfoVarObj varObj; + if (CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(varName, varObj)) + { + bool bValueChanged = false; + if (ExamineSBValueForChange(varObj, true, bValueChanged)) + { + if (bValueChanged && CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(varName, varObj)) + { + lldb::SBValue &rValue = const_cast(varObj.GetValue()); + const bool bValid = rValue.IsValid(); + const CMIUtilString strValue(bValid ? varObj.GetValueFormatted() : ""); + const CMIUtilString strInScope((bValid && rValue.IsInScope()) ? "true" : "false"); + MIFormResponse(varName, strValue, strInScope); + + m_bValueChangedCompositeType = true; + } + } + else + return MIstatus::failure; + } + } + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarUpdate::Acknowledge( void ) +bool +CMICmdCmdVarUpdate::Acknowledge(void) { - if( m_bValueChangedArrayType || m_bValueChangedNormalType ) - { - CMICmnLLDBDebugSessionInfoVarObj varObj; - CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( m_strValueName, varObj ); - lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() ); - const bool bValid = rValue.IsValid(); - const CMIUtilString strValue( bValid ? varObj.GetValueFormatted() : "" ); - const CMIUtilString strInScope( (bValid && rValue.IsInScope()) ? "true" : "false" ); - - // MI print "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]" - const CMICmnMIValueConst miValueConst( m_strValueName ); - CMICmnMIValueResult miValueResult( "name", miValueConst ); - CMICmnMIValueTuple miValueTuple( miValueResult ); - const CMICmnMIValueConst miValueConst2( strValue ); - CMICmnMIValueResult miValueResult2( "value", miValueConst2 ); - miValueTuple.Add( miValueResult2 ); - const CMICmnMIValueConst miValueConst3( strInScope ); - CMICmnMIValueResult miValueResult3( "in_scope", miValueConst3 ); - miValueTuple.Add( miValueResult3 ); - const CMICmnMIValueConst miValueConst4( "false" ); - CMICmnMIValueResult miValueResult4( "type_changed", miValueConst4 ); - miValueTuple.Add( miValueResult4 ); - const CMICmnMIValueConst miValueConst5( "0" ); - CMICmnMIValueResult miValueResult5( "has_more", miValueConst5 ); - miValueTuple.Add( miValueResult5 ); - const CMICmnMIValueList miValueList( miValueTuple ); - CMICmnMIValueResult miValueResult6( "changelist", miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6 ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; - } - else if( m_bValueChangedCompositeType ) - { - // MI print "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"},{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]" - CMICmnMIValueResult miValueResult6( "changelist", m_miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6 ); - m_miResultRecord = miRecordResult; - } - else - { - // MI: "%s^done,changelist=[]" - const CMICmnMIValueList miValueList( true ); - CMICmnMIValueResult miValueResult6( "changelist", miValueList ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6 ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - return MIstatus::success; + if (m_bValueChangedArrayType || m_bValueChangedNormalType) + { + CMICmnLLDBDebugSessionInfoVarObj varObj; + CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(m_strValueName, varObj); + lldb::SBValue &rValue = const_cast(varObj.GetValue()); + const bool bValid = rValue.IsValid(); + const CMIUtilString strValue(bValid ? varObj.GetValueFormatted() : ""); + const CMIUtilString strInScope((bValid && rValue.IsInScope()) ? "true" : "false"); + + // MI print "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]" + const CMICmnMIValueConst miValueConst(m_strValueName); + CMICmnMIValueResult miValueResult("name", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueConst miValueConst2(strValue); + CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + const CMICmnMIValueConst miValueConst3(strInScope); + CMICmnMIValueResult miValueResult3("in_scope", miValueConst3); + miValueTuple.Add(miValueResult3); + const CMICmnMIValueConst miValueConst4("false"); + CMICmnMIValueResult miValueResult4("type_changed", miValueConst4); + miValueTuple.Add(miValueResult4); + const CMICmnMIValueConst miValueConst5("0"); + CMICmnMIValueResult miValueResult5("has_more", miValueConst5); + miValueTuple.Add(miValueResult5); + const CMICmnMIValueList miValueList(miValueTuple); + CMICmnMIValueResult miValueResult6("changelist", miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6); + m_miResultRecord = miRecordResult; + + return MIstatus::success; + } + else if (m_bValueChangedCompositeType) + { + // MI print + // "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"},{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]" + CMICmnMIValueResult miValueResult6("changelist", m_miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6); + m_miResultRecord = miRecordResult; + } + else + { + // MI: "%s^done,changelist=[]" + const CMICmnMIValueList miValueList(true); + CMICmnMIValueResult miValueResult6("changelist", miValueList); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdVarUpdate::CreateSelf( void ) +CMICmdBase * +CMICmdCmdVarUpdate::CreateSelf(void) { - return new CMICmdCmdVarUpdate(); + return new CMICmdCmdVarUpdate(); } //++ ------------------------------------------------------------------------------------ -// Details: Form the MI response for multiple variables. -// Type: Method. -// Args: vrStrVarName - (R) Session var object's name. -// vrStrValue - (R) Text version of the value held in the variable. -// vrStrScope - (R) In scope "yes" or "no". -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Form the MI response for multiple variables. +// Type: Method. +// Args: vrStrVarName - (R) Session var object's name. +// vrStrValue - (R) Text version of the value held in the variable. +// vrStrScope - (R) In scope "yes" or "no". +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarUpdate::MIFormResponse( const CMIUtilString & vrStrVarName, const CMIUtilString & vrStrValue, const CMIUtilString & vrStrScope ) +bool +CMICmdCmdVarUpdate::MIFormResponse(const CMIUtilString &vrStrVarName, const CMIUtilString &vrStrValue, const CMIUtilString &vrStrScope) { - // MI print "[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]" - const CMICmnMIValueConst miValueConst( vrStrVarName ); - CMICmnMIValueResult miValueResult( "name", miValueConst ); - CMICmnMIValueTuple miValueTuple( miValueResult ); - const CMICmnMIValueConst miValueConst2( vrStrValue ); - CMICmnMIValueResult miValueResult2( "value", miValueConst2 ); - bool bOk = miValueTuple.Add( miValueResult2 ); - const CMICmnMIValueConst miValueConst3( vrStrScope ); - CMICmnMIValueResult miValueResult3( "in_scope", miValueConst3 ); - bOk = bOk && miValueTuple.Add( miValueResult3 ); - const CMICmnMIValueConst miValueConst4( "false" ); - CMICmnMIValueResult miValueResult4( "type_changed", miValueConst4 ); - bOk = bOk && miValueTuple.Add( miValueResult4 ); - const CMICmnMIValueConst miValueConst5( "0" ); - CMICmnMIValueResult miValueResult5( "has_more", miValueConst5 ); - bOk = bOk && miValueTuple.Add( miValueResult5 ); - bOk = bOk && m_miValueList.Add( miValueTuple ); - - return bOk; + // MI print "[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]" + const CMICmnMIValueConst miValueConst(vrStrVarName); + CMICmnMIValueResult miValueResult("name", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueConst miValueConst2(vrStrValue); + CMICmnMIValueResult miValueResult2("value", miValueConst2); + bool bOk = miValueTuple.Add(miValueResult2); + const CMICmnMIValueConst miValueConst3(vrStrScope); + CMICmnMIValueResult miValueResult3("in_scope", miValueConst3); + bOk = bOk && miValueTuple.Add(miValueResult3); + const CMICmnMIValueConst miValueConst4("false"); + CMICmnMIValueResult miValueResult4("type_changed", miValueConst4); + bOk = bOk && miValueTuple.Add(miValueResult4); + const CMICmnMIValueConst miValueConst5("0"); + CMICmnMIValueResult miValueResult5("has_more", miValueConst5); + bOk = bOk && miValueTuple.Add(miValueResult5); + bOk = bOk && m_miValueList.Add(miValueTuple); + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Determine if the var object is a array type variable. LLDB does not 'detect' -// a value change for some types like elements in an array so have to re-evaluate -// the expression again. -// Type: Method. -// Args: vrVarObj - (R) Session var object to examine. -// vrwbChanged - (W) True = Is an array type and it changed, -// False = Not an array type or not changed. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Determine if the var object is a array type variable. LLDB does not 'detect' +// a value change for some types like elements in an array so have to re-evaluate +// the expression again. +// Type: Method. +// Args: vrVarObj - (R) Session var object to examine. +// vrwbChanged - (W) True = Is an array type and it changed, +// False = Not an array type or not changed. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarUpdate::ExamineSBValueForChange( const CMICmnLLDBDebugSessionInfoVarObj & vrVarObj, const bool vbIgnoreVarType, bool & vrwbChanged ) +bool +CMICmdCmdVarUpdate::ExamineSBValueForChange(const CMICmnLLDBDebugSessionInfoVarObj &vrVarObj, const bool vbIgnoreVarType, bool &vrwbChanged) { - vrwbChanged = false; - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = rProcess.GetSelectedThread(); - if( thread.GetNumFrames() == 0 ) - { - return MIstatus::success; - } - - const CMIUtilString & strVarObjParentName = vrVarObj.GetVarParentName(); - lldb::SBFrame frame = thread.GetSelectedFrame(); - const CMIUtilString & rExpression( vrVarObj.GetNameReal() ); - CMIUtilString varExpression; - if( strVarObjParentName.empty() ) - { - varExpression = rExpression; - } - else - { - CMICmnLLDBDebugSessionInfoVarObj varObjParent; - if( CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( strVarObjParentName, varObjParent ) ) - varExpression = CMIUtilString::Format( "%s.%s", varObjParent.GetNameReal().c_str(), rExpression.c_str() ); - else - { - // The parent is only assigned in the CMICmdCmdVarListChildren command, we have a problem, need to investigate - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), strVarObjParentName.c_str() ) ); - return MIstatus::failure; - } - } - - lldb::SBValue value = frame.EvaluateExpression( varExpression.c_str() ); - if( !value.IsValid() ) - value = frame.FindVariable( rExpression.c_str() ); - if( value.IsValid() ) - { - lldb::SBType valueType = value.GetType(); - const lldb::BasicType eValueType = valueType.GetBasicType(); - if( vbIgnoreVarType || (eValueType != lldb::BasicType::eBasicTypeInvalid) ) - { - MIuint64 nPrevValue = 0; - MIuint64 nRevaluateValue = 0; - lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrVarObj.GetValue() ); - if( CMICmnLLDBProxySBValue::GetValueAsUnsigned( rValue, nPrevValue ) && - CMICmnLLDBProxySBValue::GetValueAsUnsigned( value, nRevaluateValue ) && - (nPrevValue != nRevaluateValue) ) - { - // Have a value change so update the var object - vrwbChanged = true; - const CMICmnLLDBDebugSessionInfoVarObj varObj( rExpression, vrVarObj.GetName(), value, strVarObjParentName ); - } - } - } - - return MIstatus::success; + vrwbChanged = false; + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + lldb::SBThread thread = rProcess.GetSelectedThread(); + if (thread.GetNumFrames() == 0) + { + return MIstatus::success; + } + + const CMIUtilString &strVarObjParentName = vrVarObj.GetVarParentName(); + lldb::SBFrame frame = thread.GetSelectedFrame(); + const CMIUtilString &rExpression(vrVarObj.GetNameReal()); + CMIUtilString varExpression; + if (strVarObjParentName.empty()) + { + varExpression = rExpression; + } + else + { + CMICmnLLDBDebugSessionInfoVarObj varObjParent; + if (CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(strVarObjParentName, varObjParent)) + varExpression = CMIUtilString::Format("%s.%s", varObjParent.GetNameReal().c_str(), rExpression.c_str()); + else + { + // The parent is only assigned in the CMICmdCmdVarListChildren command, we have a problem, need to investigate + SetError( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), strVarObjParentName.c_str())); + return MIstatus::failure; + } + } + + lldb::SBValue value = frame.EvaluateExpression(varExpression.c_str()); + if (!value.IsValid()) + value = frame.FindVariable(rExpression.c_str()); + if (value.IsValid()) + { + lldb::SBType valueType = value.GetType(); + const lldb::BasicType eValueType = valueType.GetBasicType(); + if (vbIgnoreVarType || (eValueType != lldb::BasicType::eBasicTypeInvalid)) + { + MIuint64 nPrevValue = 0; + MIuint64 nRevaluateValue = 0; + lldb::SBValue &rValue = const_cast(vrVarObj.GetValue()); + if (CMICmnLLDBProxySBValue::GetValueAsUnsigned(rValue, nPrevValue) && + CMICmnLLDBProxySBValue::GetValueAsUnsigned(value, nRevaluateValue) && (nPrevValue != nRevaluateValue)) + { + // Have a value change so update the var object + vrwbChanged = true; + const CMICmnLLDBDebugSessionInfoVarObj varObj(rExpression, vrVarObj.GetName(), value, strVarObjParentName); + } + } + } + + return MIstatus::success; } //--------------------------------------------------------------------------------------- @@ -562,95 +578,99 @@ bool CMICmdCmdVarUpdate::ExamineSBValueForChange( const CMICmnLLDBDebugSessionIn //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarDelete constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarDelete constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarDelete::CMICmdCmdVarDelete( void ) -: m_constStrArgName( "name" ) +CMICmdCmdVarDelete::CMICmdCmdVarDelete(void) + : m_constStrArgName("name") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-delete"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarDelete::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-delete"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarDelete::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarDelete::ParseArgs( void ) +bool +CMICmdCmdVarDelete::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarDelete destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarDelete destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarDelete::~CMICmdCmdVarDelete( void ) +CMICmdCmdVarDelete::~CMICmdCmdVarDelete(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarDelete::Execute( void ) +bool +CMICmdCmdVarDelete::Execute(void) { - CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName ); + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + + const CMIUtilString &rVarObjName(pArgName->GetValue()); + CMICmnLLDBDebugSessionInfoVarObj::VarObjDelete(rVarObjName); - const CMIUtilString & rVarObjName( pArgName->GetValue() ); - CMICmnLLDBDebugSessionInfoVarObj::VarObjDelete( rVarObjName ); - - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarDelete::Acknowledge( void ) +bool +CMICmdCmdVarDelete::Acknowledge(void) { - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdVarDelete::CreateSelf( void ) +CMICmdBase * +CMICmdCmdVarDelete::CreateSelf(void) { - return new CMICmdCmdVarDelete(); + return new CMICmdCmdVarDelete(); } //--------------------------------------------------------------------------------------- @@ -658,129 +678,133 @@ CMICmdBase * CMICmdCmdVarDelete::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarAssign constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarAssign constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarAssign::CMICmdCmdVarAssign( void ) -: m_bOk( true ) -, m_constStrArgName( "name" ) -, m_constStrArgExpression( "expression" ) +CMICmdCmdVarAssign::CMICmdCmdVarAssign(void) + : m_bOk(true) + , m_constStrArgName("name") + , m_constStrArgExpression("expression") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-assign"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarAssign::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-assign"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarAssign::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarAssign destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarAssign destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarAssign::~CMICmdCmdVarAssign( void ) +CMICmdCmdVarAssign::~CMICmdCmdVarAssign(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarAssign::ParseArgs( void ) +bool +CMICmdCmdVarAssign::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgExpression, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgExpression, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarAssign::Execute( void ) +bool +CMICmdCmdVarAssign::Execute(void) { - CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName ); - CMICMDBASE_GETOPTION( pArgExpression, String, m_constStrArgExpression ); - - const CMIUtilString & rVarObjName( pArgName->GetValue() ); - const CMIUtilString & rExpression( pArgExpression->GetValue() ); - - CMICmnLLDBDebugSessionInfoVarObj varObj; - if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) ); - return MIstatus::failure; - } - m_varObjName = rVarObjName; - - CMIUtilString strExpression( rExpression.Trim() ); - strExpression = strExpression.Trim( '"' ); - lldb::SBValue & rValue( const_cast< lldb::SBValue & >( varObj.GetValue() ) ); - m_bOk = rValue.SetValueFromCString( strExpression.c_str() ); - if( m_bOk ) - varObj.UpdateValue(); - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + CMICMDBASE_GETOPTION(pArgExpression, String, m_constStrArgExpression); + + const CMIUtilString &rVarObjName(pArgName->GetValue()); + const CMIUtilString &rExpression(pArgExpression->GetValue()); + + CMICmnLLDBDebugSessionInfoVarObj varObj; + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); + return MIstatus::failure; + } + m_varObjName = rVarObjName; + + CMIUtilString strExpression(rExpression.Trim()); + strExpression = strExpression.Trim('"'); + lldb::SBValue &rValue(const_cast(varObj.GetValue())); + m_bOk = rValue.SetValueFromCString(strExpression.c_str()); + if (m_bOk) + varObj.UpdateValue(); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarAssign::Acknowledge( void ) +bool +CMICmdCmdVarAssign::Acknowledge(void) { - if( m_bOk ) - { - // MI print "%s^done,value=\"%s\"" - CMICmnLLDBDebugSessionInfoVarObj varObj; - CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( m_varObjName, varObj ); - const CMICmnMIValueConst miValueConst( varObj.GetValueFormatted() ); - const CMICmnMIValueResult miValueResult( "value", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; - } - - const CMICmnMIValueConst miValueConst( "expression could not be evaluated" ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + if (m_bOk) + { + // MI print "%s^done,value=\"%s\"" + CMICmnLLDBDebugSessionInfoVarObj varObj; + CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(m_varObjName, varObj); + const CMICmnMIValueConst miValueConst(varObj.GetValueFormatted()); + const CMICmnMIValueResult miValueResult("value", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; + } + + const CMICmnMIValueConst miValueConst("expression could not be evaluated"); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdVarAssign::CreateSelf( void ) +CMICmdBase * +CMICmdCmdVarAssign::CreateSelf(void) { - return new CMICmdCmdVarAssign(); + return new CMICmdCmdVarAssign(); } //--------------------------------------------------------------------------------------- @@ -788,135 +812,140 @@ CMICmdBase * CMICmdCmdVarAssign::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarSetFormat constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarSetFormat constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarSetFormat::CMICmdCmdVarSetFormat( void ) -: m_constStrArgName( "name" ) -, m_constStrArgFormatSpec( "format-spec" ) +CMICmdCmdVarSetFormat::CMICmdCmdVarSetFormat(void) + : m_constStrArgName("name") + , m_constStrArgFormatSpec("format-spec") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-set-format"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarSetFormat::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-set-format"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarSetFormat::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarSetFormat destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarSetFormat destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarSetFormat::~CMICmdCmdVarSetFormat( void ) +CMICmdCmdVarSetFormat::~CMICmdCmdVarSetFormat(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarSetFormat::ParseArgs( void ) +bool +CMICmdCmdVarSetFormat::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgFormatSpec, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgFormatSpec, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarSetFormat::Execute( void ) +bool +CMICmdCmdVarSetFormat::Execute(void) { - CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName ); - CMICMDBASE_GETOPTION( pArgFormatSpec, String, m_constStrArgFormatSpec ); - - const CMIUtilString & rVarObjName( pArgName->GetValue() ); - const CMIUtilString & rExpression( pArgFormatSpec->GetValue() ); - - CMICmnLLDBDebugSessionInfoVarObj varObj; - if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) ); - return MIstatus::failure; - } - if( !varObj.SetVarFormat( CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForString( rExpression ) ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_ENUM_INVALID ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str(), rExpression.c_str() ) ); - return MIstatus::failure; - } - varObj.UpdateValue(); - - m_varObjName = rVarObjName; - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + CMICMDBASE_GETOPTION(pArgFormatSpec, String, m_constStrArgFormatSpec); + + const CMIUtilString &rVarObjName(pArgName->GetValue()); + const CMIUtilString &rExpression(pArgFormatSpec->GetValue()); + + CMICmnLLDBDebugSessionInfoVarObj varObj; + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); + return MIstatus::failure; + } + if (!varObj.SetVarFormat(CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForString(rExpression))) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_ENUM_INVALID), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str(), + rExpression.c_str())); + return MIstatus::failure; + } + varObj.UpdateValue(); + + m_varObjName = rVarObjName; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarSetFormat::Acknowledge( void ) +bool +CMICmdCmdVarSetFormat::Acknowledge(void) { - // MI print "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]" - CMICmnLLDBDebugSessionInfoVarObj varObj; - CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( m_varObjName, varObj ); - const CMICmnMIValueConst miValueConst( m_varObjName ); - const CMICmnMIValueResult miValueResult( "name", miValueConst ); - CMICmnMIValueTuple miValueTuple( miValueResult ); - const CMICmnMIValueConst miValueConst2( varObj.GetValueFormatted() ); - const CMICmnMIValueResult miValueResult2( "value", miValueConst2 ); - miValueTuple.Add( miValueResult2 ); - lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() ); - const CMICmnMIValueConst miValueConst3( rValue.IsInScope() ? "true" : "false" ); - const CMICmnMIValueResult miValueResult3( "in_scope", miValueConst3 ); - miValueTuple.Add( miValueResult3 ); - const CMICmnMIValueConst miValueConst4( "false" ); - const CMICmnMIValueResult miValueResult4( "type_changed", miValueConst4 ); - miValueTuple.Add( miValueResult4 ); - const CMICmnMIValueConst miValueConst5( "0" ); - const CMICmnMIValueResult miValueResult5( "type_changed", miValueConst5 ); - miValueTuple.Add( miValueResult5 ); - const CMICmnMIValueList miValueList( miValueTuple ); - const CMICmnMIValueResult miValueResult6( "changelist", miValueList ); - - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6 ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + // MI print "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]" + CMICmnLLDBDebugSessionInfoVarObj varObj; + CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(m_varObjName, varObj); + const CMICmnMIValueConst miValueConst(m_varObjName); + const CMICmnMIValueResult miValueResult("name", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueConst miValueConst2(varObj.GetValueFormatted()); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + lldb::SBValue &rValue = const_cast(varObj.GetValue()); + const CMICmnMIValueConst miValueConst3(rValue.IsInScope() ? "true" : "false"); + const CMICmnMIValueResult miValueResult3("in_scope", miValueConst3); + miValueTuple.Add(miValueResult3); + const CMICmnMIValueConst miValueConst4("false"); + const CMICmnMIValueResult miValueResult4("type_changed", miValueConst4); + miValueTuple.Add(miValueResult4); + const CMICmnMIValueConst miValueConst5("0"); + const CMICmnMIValueResult miValueResult5("type_changed", miValueConst5); + miValueTuple.Add(miValueResult5); + const CMICmnMIValueList miValueList(miValueTuple); + const CMICmnMIValueResult miValueResult6("changelist", miValueList); + + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdVarSetFormat::CreateSelf( void ) +CMICmdBase * +CMICmdCmdVarSetFormat::CreateSelf(void) { - return new CMICmdCmdVarSetFormat(); + return new CMICmdCmdVarSetFormat(); } //--------------------------------------------------------------------------------------- @@ -924,186 +953,190 @@ CMICmdBase * CMICmdCmdVarSetFormat::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarListChildren constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarListChildren constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarListChildren::CMICmdCmdVarListChildren( void ) -: m_bValueValid( false ) -, m_nChildren( 0 ) -, m_constStrArgPrintValues( "print-values" ) -, m_constStrArgName( "name" ) +CMICmdCmdVarListChildren::CMICmdCmdVarListChildren(void) + : m_bValueValid(false) + , m_nChildren(0) + , m_constStrArgPrintValues("print-values") + , m_constStrArgName("name") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-list-children"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarListChildren::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-list-children"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarListChildren::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarListChildren destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarListChildren destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarListChildren::~CMICmdCmdVarListChildren( void ) +CMICmdCmdVarListChildren::~CMICmdCmdVarListChildren(void) { - m_vecMiValueResult.clear(); + m_vecMiValueResult.clear(); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarListChildren::ParseArgs( void ) +bool +CMICmdCmdVarListChildren::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgPrintValues, false, false ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgPrintValues, false, false))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarListChildren::Execute( void ) +bool +CMICmdCmdVarListChildren::Execute(void) { - CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName ); - - const CMIUtilString & rVarObjName( pArgName->GetValue() ); - CMICmnLLDBDebugSessionInfoVarObj varObj; - if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) ); - return MIstatus::failure; - } - - lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() ); - m_bValueValid = rValue.IsValid(); - if( !m_bValueValid ) - return MIstatus::success; - - m_vecMiValueResult.clear(); - m_nChildren = rValue.GetNumChildren(); - for( MIuint i = 0; i < m_nChildren; i++ ) - { - lldb::SBValue member = rValue.GetChildAtIndex( i ); - if( !member.IsValid() ) - continue; - const CMICmnLLDBUtilSBValue utilValue( member ); - const CMIUtilString strExp = utilValue.GetName(); - const CMIUtilString name( CMIUtilString::Format( "%s.%s", rVarObjName.c_str(), strExp.c_str() ) ); - const MIuint nChildren = member.GetNumChildren(); - const CMIUtilString strThreadId( CMIUtilString::Format( "%u", member.GetThread().GetIndexID() ) ); - - // Varobj gets added to CMICmnLLDBDebugSessionInfoVarObj static container of varObjs - CMICmnLLDBDebugSessionInfoVarObj var( strExp, name, member, rVarObjName ); - - // MI print "child={name=\"%s\",exp=\"%s\",numchild=\"%d\",value=\"%s\",type=\"%s\",thread-id=\"%u\",has_more=\"%u\"}" - const CMICmnMIValueConst miValueConst( name ); - const CMICmnMIValueResult miValueResult( "name", miValueConst ); - CMICmnMIValueTuple miValueTuple( miValueResult ); - const CMICmnMIValueConst miValueConst2( strExp ); - const CMICmnMIValueResult miValueResult2( "exp", miValueConst2 ); - miValueTuple.Add( miValueResult2 ); - const CMIUtilString strNumChild( CMIUtilString::Format( "%d", nChildren ) ); - const CMICmnMIValueConst miValueConst3( strNumChild ); - const CMICmnMIValueResult miValueResult3( "numchild", miValueConst3 ); - miValueTuple.Add( miValueResult3 ); - const CMICmnMIValueConst miValueConst5( utilValue.GetTypeNameDisplay() ); - const CMICmnMIValueResult miValueResult5( "type", miValueConst5 ); - miValueTuple.Add( miValueResult5 ); - const CMICmnMIValueConst miValueConst6( strThreadId ); - const CMICmnMIValueResult miValueResult6( "thread-id", miValueConst6 ); - miValueTuple.Add( miValueResult6 ); - const CMICmnMIValueConst miValueConst7( "0" ); - const CMICmnMIValueResult miValueResult7( "has_more", miValueConst7 ); - miValueTuple.Add( miValueResult7 ); - const CMICmnMIValueResult miValueResult8( "child", miValueTuple ); - m_vecMiValueResult.push_back( miValueResult8 ); - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + + const CMIUtilString &rVarObjName(pArgName->GetValue()); + CMICmnLLDBDebugSessionInfoVarObj varObj; + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); + return MIstatus::failure; + } + + lldb::SBValue &rValue = const_cast(varObj.GetValue()); + m_bValueValid = rValue.IsValid(); + if (!m_bValueValid) + return MIstatus::success; + + m_vecMiValueResult.clear(); + m_nChildren = rValue.GetNumChildren(); + for (MIuint i = 0; i < m_nChildren; i++) + { + lldb::SBValue member = rValue.GetChildAtIndex(i); + if (!member.IsValid()) + continue; + const CMICmnLLDBUtilSBValue utilValue(member); + const CMIUtilString strExp = utilValue.GetName(); + const CMIUtilString name(CMIUtilString::Format("%s.%s", rVarObjName.c_str(), strExp.c_str())); + const MIuint nChildren = member.GetNumChildren(); + const CMIUtilString strThreadId(CMIUtilString::Format("%u", member.GetThread().GetIndexID())); + + // Varobj gets added to CMICmnLLDBDebugSessionInfoVarObj static container of varObjs + CMICmnLLDBDebugSessionInfoVarObj var(strExp, name, member, rVarObjName); + + // MI print "child={name=\"%s\",exp=\"%s\",numchild=\"%d\",value=\"%s\",type=\"%s\",thread-id=\"%u\",has_more=\"%u\"}" + const CMICmnMIValueConst miValueConst(name); + const CMICmnMIValueResult miValueResult("name", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueConst miValueConst2(strExp); + const CMICmnMIValueResult miValueResult2("exp", miValueConst2); + miValueTuple.Add(miValueResult2); + const CMIUtilString strNumChild(CMIUtilString::Format("%d", nChildren)); + const CMICmnMIValueConst miValueConst3(strNumChild); + const CMICmnMIValueResult miValueResult3("numchild", miValueConst3); + miValueTuple.Add(miValueResult3); + const CMICmnMIValueConst miValueConst5(utilValue.GetTypeNameDisplay()); + const CMICmnMIValueResult miValueResult5("type", miValueConst5); + miValueTuple.Add(miValueResult5); + const CMICmnMIValueConst miValueConst6(strThreadId); + const CMICmnMIValueResult miValueResult6("thread-id", miValueConst6); + miValueTuple.Add(miValueResult6); + const CMICmnMIValueConst miValueConst7("0"); + const CMICmnMIValueResult miValueResult7("has_more", miValueConst7); + miValueTuple.Add(miValueResult7); + const CMICmnMIValueResult miValueResult8("child", miValueTuple); + m_vecMiValueResult.push_back(miValueResult8); + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarListChildren::Acknowledge( void ) +bool +CMICmdCmdVarListChildren::Acknowledge(void) { - if( m_bValueValid ) - { - // MI print "%s^done,numchild=\"%u\",children=[]"" - const CMIUtilString strNumChild( CMIUtilString::Format( "%u", m_nChildren ) ); - const CMICmnMIValueConst miValueConst( strNumChild ); - CMICmnMIValueResult miValueResult( "numchild", miValueConst ); - - VecMIValueResult_t::const_iterator it = m_vecMiValueResult.begin(); - if( it == m_vecMiValueResult.end() ) - { - const CMICmnMIValueConst miValueConst( "[]" ); - miValueResult.Add( "children", miValueConst ); - } - else - { - CMICmnMIValueList miValueList( *it ); - ++it; - while( it != m_vecMiValueResult.end() ) - { - const CMICmnMIValueResult & rResult( *it ); - miValueList.Add( rResult ); - - // Next - ++it; - } - miValueResult.Add( "children", miValueList ); - } - - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - // MI print "%s^done,numchild=\"0\"" - const CMICmnMIValueConst miValueConst( "0" ); - const CMICmnMIValueResult miValueResult( "numchild", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + if (m_bValueValid) + { + // MI print "%s^done,numchild=\"%u\",children=[]"" + const CMIUtilString strNumChild(CMIUtilString::Format("%u", m_nChildren)); + const CMICmnMIValueConst miValueConst(strNumChild); + CMICmnMIValueResult miValueResult("numchild", miValueConst); + + VecMIValueResult_t::const_iterator it = m_vecMiValueResult.begin(); + if (it == m_vecMiValueResult.end()) + { + const CMICmnMIValueConst miValueConst("[]"); + miValueResult.Add("children", miValueConst); + } + else + { + CMICmnMIValueList miValueList(*it); + ++it; + while (it != m_vecMiValueResult.end()) + { + const CMICmnMIValueResult &rResult(*it); + miValueList.Add(rResult); + + // Next + ++it; + } + miValueResult.Add("children", miValueList); + } + + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + // MI print "%s^done,numchild=\"0\"" + const CMICmnMIValueConst miValueConst("0"); + const CMICmnMIValueResult miValueResult("numchild", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdVarListChildren::CreateSelf( void ) +CMICmdBase * +CMICmdCmdVarListChildren::CreateSelf(void) { - return new CMICmdCmdVarListChildren(); + return new CMICmdCmdVarListChildren(); } //--------------------------------------------------------------------------------------- @@ -1111,123 +1144,128 @@ CMICmdBase * CMICmdCmdVarListChildren::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarEvaluateExpression constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarEvaluateExpression constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarEvaluateExpression::CMICmdCmdVarEvaluateExpression( void ) -: m_bValueValid( true ) -, m_constStrArgFormatSpec( "-f" ) -, m_constStrArgName( "name" ) +CMICmdCmdVarEvaluateExpression::CMICmdCmdVarEvaluateExpression(void) + : m_bValueValid(true) + , m_constStrArgFormatSpec("-f") + , m_constStrArgName("name") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-evaluate-expression"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarEvaluateExpression::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-evaluate-expression"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarEvaluateExpression::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarEvaluateExpression destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarEvaluateExpression destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarEvaluateExpression::~CMICmdCmdVarEvaluateExpression( void ) +CMICmdCmdVarEvaluateExpression::~CMICmdCmdVarEvaluateExpression(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarEvaluateExpression::ParseArgs( void ) +bool +CMICmdCmdVarEvaluateExpression::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgFormatSpec, false, false, CMICmdArgValListBase::eArgValType_String, 1 ) ) ); - bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add( + *(new CMICmdArgValOptionShort(m_constStrArgFormatSpec, false, false, CMICmdArgValListBase::eArgValType_String, 1))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarEvaluateExpression::Execute( void ) +bool +CMICmdCmdVarEvaluateExpression::Execute(void) { - CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName ); + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); - const CMIUtilString & rVarObjName( pArgName->GetValue() ); - CMICmnLLDBDebugSessionInfoVarObj varObj; - if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) ); - return MIstatus::failure; - } + const CMIUtilString &rVarObjName(pArgName->GetValue()); + CMICmnLLDBDebugSessionInfoVarObj varObj; + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); + return MIstatus::failure; + } - lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() ); - m_bValueValid = rValue.IsValid(); - if( !m_bValueValid ) - return MIstatus::success; + lldb::SBValue &rValue = const_cast(varObj.GetValue()); + m_bValueValid = rValue.IsValid(); + if (!m_bValueValid) + return MIstatus::success; - m_varObjName = rVarObjName; - varObj.UpdateValue(); + m_varObjName = rVarObjName; + varObj.UpdateValue(); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarEvaluateExpression::Acknowledge( void ) +bool +CMICmdCmdVarEvaluateExpression::Acknowledge(void) { - if( m_bValueValid ) - { - CMICmnLLDBDebugSessionInfoVarObj varObj; - CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( m_varObjName, varObj ); - const CMICmnMIValueConst miValueConst( varObj.GetValueFormatted() ); - const CMICmnMIValueResult miValueResult( "value", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - const CMICmnMIValueConst miValueConst( "variable invalid" ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; + if (m_bValueValid) + { + CMICmnLLDBDebugSessionInfoVarObj varObj; + CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(m_varObjName, varObj); + const CMICmnMIValueConst miValueConst(varObj.GetValueFormatted()); + const CMICmnMIValueResult miValueResult("value", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + const CMICmnMIValueConst miValueConst("variable invalid"); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdVarEvaluateExpression::CreateSelf( void ) +CMICmdBase * +CMICmdCmdVarEvaluateExpression::CreateSelf(void) { - return new CMICmdCmdVarEvaluateExpression(); + return new CMICmdCmdVarEvaluateExpression(); } //--------------------------------------------------------------------------------------- @@ -1235,156 +1273,160 @@ CMICmdBase * CMICmdCmdVarEvaluateExpression::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarInfoPathExpression constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarInfoPathExpression constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarInfoPathExpression::CMICmdCmdVarInfoPathExpression( void ) -: m_bValueValid( true ) -, m_constStrArgName( "name" ) +CMICmdCmdVarInfoPathExpression::CMICmdCmdVarInfoPathExpression(void) + : m_bValueValid(true) + , m_constStrArgName("name") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-info-path-expression"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarInfoPathExpression::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-info-path-expression"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarInfoPathExpression::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarInfoPathExpression destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarInfoPathExpression destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarInfoPathExpression::~CMICmdCmdVarInfoPathExpression( void ) +CMICmdCmdVarInfoPathExpression::~CMICmdCmdVarInfoPathExpression(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarInfoPathExpression::ParseArgs( void ) +bool +CMICmdCmdVarInfoPathExpression::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarInfoPathExpression::Execute( void ) +bool +CMICmdCmdVarInfoPathExpression::Execute(void) { - CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName ); - - const CMIUtilString & rVarObjName( pArgName->GetValue() ); - CMICmnLLDBDebugSessionInfoVarObj varObj; - if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) ); - return MIstatus::failure; - } - - lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() ); - m_bValueValid = rValue.IsValid(); - if( !m_bValueValid ) - return MIstatus::success; - - lldb::SBStream stream; - if( !rValue.GetExpressionPath( stream, true ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) ); - return MIstatus::failure; - } - - const MIchar * pPathExpression = stream.GetData(); - if( pPathExpression == nullptr ) - { - // Build expression from what we do know - m_strPathExpression = varObj.GetNameReal(); - return MIstatus::success; - } - - // Has LLDB returned a var signature of it's own - if( pPathExpression[ 0 ] != '$' ) - { - m_strPathExpression = pPathExpression; - return MIstatus::success; - } - - // Build expression from what we do know - const CMIUtilString & rVarParentName( varObj.GetVarParentName() ); - if( rVarParentName.empty() ) - { - m_strPathExpression = varObj.GetNameReal(); - } - else - { - CMICmnLLDBDebugSessionInfoVarObj varObjParent; - if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarParentName, varObjParent ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarParentName.c_str() ) ); - return MIstatus::failure; - } - m_strPathExpression = CMIUtilString::Format( "%s.%s", varObjParent.GetNameReal().c_str(), varObj.GetNameReal().c_str() ); - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + + const CMIUtilString &rVarObjName(pArgName->GetValue()); + CMICmnLLDBDebugSessionInfoVarObj varObj; + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); + return MIstatus::failure; + } + + lldb::SBValue &rValue = const_cast(varObj.GetValue()); + m_bValueValid = rValue.IsValid(); + if (!m_bValueValid) + return MIstatus::success; + + lldb::SBStream stream; + if (!rValue.GetExpressionPath(stream, true)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); + return MIstatus::failure; + } + + const MIchar *pPathExpression = stream.GetData(); + if (pPathExpression == nullptr) + { + // Build expression from what we do know + m_strPathExpression = varObj.GetNameReal(); + return MIstatus::success; + } + + // Has LLDB returned a var signature of it's own + if (pPathExpression[0] != '$') + { + m_strPathExpression = pPathExpression; + return MIstatus::success; + } + + // Build expression from what we do know + const CMIUtilString &rVarParentName(varObj.GetVarParentName()); + if (rVarParentName.empty()) + { + m_strPathExpression = varObj.GetNameReal(); + } + else + { + CMICmnLLDBDebugSessionInfoVarObj varObjParent; + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarParentName, varObjParent)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarParentName.c_str())); + return MIstatus::failure; + } + m_strPathExpression = CMIUtilString::Format("%s.%s", varObjParent.GetNameReal().c_str(), varObj.GetNameReal().c_str()); + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarInfoPathExpression::Acknowledge( void ) +bool +CMICmdCmdVarInfoPathExpression::Acknowledge(void) { - if( m_bValueValid ) - { - const CMICmnMIValueConst miValueConst( m_strPathExpression ); - const CMICmnMIValueResult miValueResult( "path_expr", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - const CMICmnMIValueConst miValueConst( "variable invalid" ); - const CMICmnMIValueResult miValueResult( "msg", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + if (m_bValueValid) + { + const CMICmnMIValueConst miValueConst(m_strPathExpression); + const CMICmnMIValueResult miValueResult("path_expr", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + const CMICmnMIValueConst miValueConst("variable invalid"); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdVarInfoPathExpression::CreateSelf( void ) +CMICmdBase * +CMICmdCmdVarInfoPathExpression::CreateSelf(void) { - return new CMICmdCmdVarInfoPathExpression(); + return new CMICmdCmdVarInfoPathExpression(); } //--------------------------------------------------------------------------------------- @@ -1392,101 +1434,105 @@ CMICmdBase * CMICmdCmdVarInfoPathExpression::CreateSelf( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarShowAttributes constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarShowAttributes constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarShowAttributes::CMICmdCmdVarShowAttributes( void ) -: m_constStrArgName( "name" ) +CMICmdCmdVarShowAttributes::CMICmdCmdVarShowAttributes(void) + : m_constStrArgName("name") { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-show-attributes"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarShowAttributes::CreateSelf; + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-show-attributes"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarShowAttributes::CreateSelf; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdCmdVarShowAttributes destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdCmdVarShowAttributes destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdCmdVarShowAttributes::~CMICmdCmdVarShowAttributes( void ) +CMICmdCmdVarShowAttributes::~CMICmdCmdVarShowAttributes(void) { } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options -// arguments to extract values for each of those arguments. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The parses the command line options +// arguments to extract values for each of those arguments. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarShowAttributes::ParseArgs( void ) +bool +CMICmdCmdVarShowAttributes::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) ); - return (bOk && ParseValidateCmdOptions() ); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true))); + return (bOk && ParseValidateCmdOptions()); } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarShowAttributes::Execute( void ) +bool +CMICmdCmdVarShowAttributes::Execute(void) { - CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName ); - - const CMIUtilString & rVarObjName( pArgName->GetValue() ); - CMICmnLLDBDebugSessionInfoVarObj varObj; - if( CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) ) - { - SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) ); - return MIstatus::failure; - } - - return MIstatus::success; + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + + const CMIUtilString &rVarObjName(pArgName->GetValue()); + CMICmnLLDBDebugSessionInfoVarObj varObj; + if (CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); + return MIstatus::failure; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result -// for the work carried out in the Execute(). -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdCmdVarShowAttributes::Acknowledge( void ) +bool +CMICmdCmdVarShowAttributes::Acknowledge(void) { - // MI output: "%s^done,status=\"editable\"]" - const CMICmnMIValueConst miValueConst( "editable" ); - const CMICmnMIValueResult miValueResult( "status", miValueConst ); - const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); - m_miResultRecord = miRecordResult; - - return MIstatus::success; + // MI output: "%s^done,status=\"editable\"]" + const CMICmnMIValueConst miValueConst("editable"); + const CMICmnMIValueResult miValueResult("status", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory -// calls this function to create an instance of *this command. -// Type: Static method. -// Args: None. -// Return: CMICmdBase * - Pointer to a new command. -// Throws: None. +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. //-- -CMICmdBase * CMICmdCmdVarShowAttributes::CreateSelf( void ) +CMICmdBase * +CMICmdCmdVarShowAttributes::CreateSelf(void) { - return new CMICmdCmdVarShowAttributes(); + return new CMICmdCmdVarShowAttributes(); } diff --git a/tools/lldb-mi/MICmdCmdVar.h b/tools/lldb-mi/MICmdCmdVar.h index 387cfc4ada83..34ce9e15af6c 100644 --- a/tools/lldb-mi/MICmdCmdVar.h +++ b/tools/lldb-mi/MICmdCmdVar.h @@ -8,32 +8,32 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCmdVar.h +// File: MICmdCmdVar.h // -// Overview: CMICmdCmdVarCreate interface. -// CMICmdCmdVarUpdate interface. -// CMICmdCmdVarDelete interface. -// CMICmdCmdVarAssign interface. -// CMICmdCmdVarSetFormat interface. -// CMICmdCmdVarListChildren interface. -// CMICmdCmdVarEvaluateExpression interface. -// CMICmdCmdVarInfoPathExpression interface. -// CMICmdCmdVarShowAttributes interface. +// Overview: CMICmdCmdVarCreate interface. +// CMICmdCmdVarUpdate interface. +// CMICmdCmdVarDelete interface. +// CMICmdCmdVarAssign interface. +// CMICmdCmdVarSetFormat interface. +// CMICmdCmdVarListChildren interface. +// CMICmdCmdVarEvaluateExpression interface. +// CMICmdCmdVarInfoPathExpression interface. +// CMICmdCmdVarShowAttributes interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery -// command class as an example. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// command class as an example. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -48,335 +48,333 @@ class CMICmnLLDBDebugSessionInfoVarObj; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "var-create". -// Gotchas: None. -// Authors: Illya Rudkin 24/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "var-create". +// Gotchas: None. +// Authors: Illya Rudkin 24/03/2014. +// Changes: None. //-- class CMICmdCmdVarCreate : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdVarCreate( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdVarCreate( void ); - -// Attribute: -private: - CMIUtilString m_strVarName; - MIuint m_nChildren; - MIuint m_nMore; - MIuint64 m_nThreadId; - CMIUtilString m_strType; - bool m_bValid; // True = Variable is valid, false = not valid - CMIUtilString m_strExpression; - CMIUtilString m_strValue; - const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgThreadGroup; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgName; - const CMIUtilString m_constStrArgFrameAddr; - const CMIUtilString m_constStrArgExpression; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdVarCreate(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdVarCreate(void); + + // Attribute: + private: + CMIUtilString m_strVarName; + MIuint m_nChildren; + MIuint64 m_nThreadId; + CMIUtilString m_strType; + bool m_bValid; // True = Variable is valid, false = not valid + CMIUtilString m_strExpression; + CMIUtilString m_strValue; + const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgThreadGroup; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option + const CMIUtilString m_constStrArgName; + const CMIUtilString m_constStrArgFrameAddr; + const CMIUtilString m_constStrArgExpression; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "var-update". -// Gotchas: None. -// Authors: Illya Rudkin 25/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "var-update". +// Gotchas: None. +// Authors: Illya Rudkin 25/03/2014. +// Changes: None. //-- class CMICmdCmdVarUpdate : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdVarUpdate( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - -// Overridden: -public: - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdVarUpdate( void ); - -// Methods: -private: - bool ExamineSBValueForChange( const CMICmnLLDBDebugSessionInfoVarObj & vrVarObj, const bool vbIgnoreVarType, bool & vrwbChanged ); - bool MIFormResponse( const CMIUtilString & vrStrVarName, const CMIUtilString & vrStrValue, const CMIUtilString & vrStrScope ); - -// Attribute: -private: - CMIUtilString m_strValueName; - const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command - const CMIUtilString m_constStrArgName; - bool m_bValueChangedArrayType; // True = yes value changed, false = no change - bool m_bValueChangedCompositeType; // True = yes value changed, false = no change - bool m_bValueChangedNormalType; // True = yes value changed, false = no change - CMICmnMIValueList m_miValueList; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdVarUpdate(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + + // Overridden: + public: + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdVarUpdate(void); + + // Methods: + private: + bool ExamineSBValueForChange(const CMICmnLLDBDebugSessionInfoVarObj &vrVarObj, const bool vbIgnoreVarType, bool &vrwbChanged); + bool MIFormResponse(const CMIUtilString &vrStrVarName, const CMIUtilString &vrStrValue, const CMIUtilString &vrStrScope); + + // Attribute: + private: + CMIUtilString m_strValueName; + const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command + const CMIUtilString m_constStrArgName; + bool m_bValueChangedArrayType; // True = yes value changed, false = no change + bool m_bValueChangedCompositeType; // True = yes value changed, false = no change + bool m_bValueChangedNormalType; // True = yes value changed, false = no change + CMICmnMIValueList m_miValueList; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "var-delete". -// Gotchas: None. -// Authors: Illya Rudkin 25/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "var-delete". +// Gotchas: None. +// Authors: Illya Rudkin 25/03/2014. +// Changes: None. //-- class CMICmdCmdVarDelete : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdVarDelete( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdVarDelete( void ); - -// Attribute: -private: - const CMIUtilString m_constStrArgName; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdVarDelete(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdVarDelete(void); + + // Attribute: + private: + const CMIUtilString m_constStrArgName; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "var-assign". -// Gotchas: None. -// Authors: Illya Rudkin 25/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "var-assign". +// Gotchas: None. +// Authors: Illya Rudkin 25/03/2014. +// Changes: None. //-- class CMICmdCmdVarAssign : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdVarAssign( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdVarAssign( void ); - -// Attributes: -private: - bool m_bOk; // True = success, false = failure - CMIUtilString m_varObjName; - const CMIUtilString m_constStrArgName; - const CMIUtilString m_constStrArgExpression; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdVarAssign(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdVarAssign(void); + + // Attributes: + private: + bool m_bOk; // True = success, false = failure + CMIUtilString m_varObjName; + const CMIUtilString m_constStrArgName; + const CMIUtilString m_constStrArgExpression; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "var-set-format". -// Gotchas: None. -// Authors: Illya Rudkin 26/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "var-set-format". +// Gotchas: None. +// Authors: Illya Rudkin 26/03/2014. +// Changes: None. //-- class CMICmdCmdVarSetFormat : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdVarSetFormat( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdVarSetFormat( void ); - -// Attributes: -private: - CMIUtilString m_varObjName; - const CMIUtilString m_constStrArgName; - const CMIUtilString m_constStrArgFormatSpec; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdVarSetFormat(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdVarSetFormat(void); + + // Attributes: + private: + CMIUtilString m_varObjName; + const CMIUtilString m_constStrArgName; + const CMIUtilString m_constStrArgFormatSpec; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "var-list-children". -// Gotchas: None. -// Authors: Illya Rudkin 26/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "var-list-children". +// Gotchas: None. +// Authors: Illya Rudkin 26/03/2014. +// Changes: None. //-- class CMICmdCmdVarListChildren : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdVarListChildren( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdVarListChildren( void ); - -// Typedefs: -private: - typedef std::vector< CMICmnMIValueResult > VecMIValueResult_t; - -// Attributes: -private: - bool m_bValueValid; // True = yes SBValue object is valid, false = not valid - VecMIValueResult_t m_vecMiValueResult; - MIuint m_nChildren; - const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command - const CMIUtilString m_constStrArgName; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdVarListChildren(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdVarListChildren(void); + + // Typedefs: + private: + typedef std::vector VecMIValueResult_t; + + // Attributes: + private: + bool m_bValueValid; // True = yes SBValue object is valid, false = not valid + VecMIValueResult_t m_vecMiValueResult; + MIuint m_nChildren; + const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command + const CMIUtilString m_constStrArgName; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "var-evaluate-expression". -// Gotchas: None. -// Authors: Illya Rudkin 26/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "var-evaluate-expression". +// Gotchas: None. +// Authors: Illya Rudkin 26/03/2014. +// Changes: None. //-- class CMICmdCmdVarEvaluateExpression : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdVarEvaluateExpression( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdVarEvaluateExpression( void ); - -// Attributes: -private: - bool m_bValueValid; // True = yes SBValue object is valid, false = not valid - CMIUtilString m_varObjName; - const CMIUtilString m_constStrArgFormatSpec; // Not handled by *this command - const CMIUtilString m_constStrArgName; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdVarEvaluateExpression(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdVarEvaluateExpression(void); + + // Attributes: + private: + bool m_bValueValid; // True = yes SBValue object is valid, false = not valid + CMIUtilString m_varObjName; + const CMIUtilString m_constStrArgFormatSpec; // Not handled by *this command + const CMIUtilString m_constStrArgName; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "var-info-path-expression". -// Gotchas: None. -// Authors: Illya Rudkin 26/03/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "var-info-path-expression". +// Gotchas: None. +// Authors: Illya Rudkin 26/03/2014. +// Changes: None. //-- class CMICmdCmdVarInfoPathExpression : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdVarInfoPathExpression( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdVarInfoPathExpression( void ); - -// Attributes: -private: - bool m_bValueValid; // True = yes SBValue object is valid, false = not valid - CMIUtilString m_strPathExpression; - const CMIUtilString m_constStrArgName; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdVarInfoPathExpression(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdVarInfoPathExpression(void); + + // Attributes: + private: + bool m_bValueValid; // True = yes SBValue object is valid, false = not valid + CMIUtilString m_strPathExpression; + const CMIUtilString m_constStrArgName; }; //++ ============================================================================ -// Details: MI command class. MI commands derived from the command base class. -// *this class implements MI command "var-show-attributes". -// Gotchas: None. -// Authors: Illya Rudkin 19/05/2014. -// Changes: None. +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "var-show-attributes". +// Gotchas: None. +// Authors: Illya Rudkin 19/05/2014. +// Changes: None. //-- class CMICmdCmdVarShowAttributes : public CMICmdBase { -// Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase * CreateSelf( void ); - -// Methods: -public: - /* ctor */ CMICmdCmdVarShowAttributes( void ); - -// Overridden: -public: - // From CMICmdInvoker::ICmd - virtual bool Execute( void ); - virtual bool Acknowledge( void ); - virtual bool ParseArgs( void ); - // From CMICmnBase - /* dtor */ virtual ~CMICmdCmdVarShowAttributes( void ); - -// Attributes: -private: - const CMIUtilString m_constStrArgName; + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdVarShowAttributes(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + virtual bool ParseArgs(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdVarShowAttributes(void); + + // Attributes: + private: + const CMIUtilString m_constStrArgName; }; - diff --git a/tools/lldb-mi/MICmdCommands.cpp b/tools/lldb-mi/MICmdCommands.cpp index 4187b059b395..81d10e1ce559 100644 --- a/tools/lldb-mi/MICmdCommands.cpp +++ b/tools/lldb-mi/MICmdCommands.cpp @@ -8,22 +8,22 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCommands.cpp +// File: MICmdCommands.cpp // -// Overview: MI command are registered with the MI command factory. +// Overview: MI command are registered with the MI command factory. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -49,87 +49,88 @@ namespace MICmnCommands { - template< typename T > - static bool Register( void ); +template static bool Register(void); } //++ ------------------------------------------------------------------------------------ -// Details: Command to command factory registration function. -// Type: Template function. -// Args: typename T - A command type class. -// Return: bool - True = yes command is registered, false = command failed to register. -// Throws: None. +// Details: Command to command factory registration function. +// Type: Template function. +// Args: typename T - A command type class. +// Return: bool - True = yes command is registered, false = command failed to register. +// Throws: None. //-- -template< typename T > -static bool MICmnCommands::Register( void ) -{ - static CMICmdFactory & rCmdFactory = CMICmdFactory::Instance(); - const CMIUtilString strMiCmd = T().GetMiCmd(); - CMICmdFactory::CmdCreatorFnPtr fn = T().GetCmdCreatorFn(); - return rCmdFactory.CmdRegister( strMiCmd, fn ); -} +template +static bool +MICmnCommands::Register(void) +{ + static CMICmdFactory &rCmdFactory = CMICmdFactory::Instance(); + const CMIUtilString strMiCmd = T().GetMiCmd(); + CMICmdFactory::CmdCreatorFnPtr fn = T().GetCmdCreatorFn(); + return rCmdFactory.CmdRegister(strMiCmd, fn); +} //++ ------------------------------------------------------------------------------------ -// Details: Register commands with MI command factory -// Type: Function. -// Args: None. -// Return: bool - True = yes all commands are registered, -// false = one or more commands failed to register. -// Throws: None. +// Details: Register commands with MI command factory +// Type: Function. +// Args: None. +// Return: bool - True = yes all commands are registered, +// false = one or more commands failed to register. +// Throws: None. //-- -bool MICmnCommands::RegisterAll( void ) +bool +MICmnCommands::RegisterAll(void) { - bool bOk = MIstatus::success; + bool bOk = MIstatus::success; - bOk &= Register< CMICmdCmdSupportInfoMiCmdQuery >(); - bOk &= Register< CMICmdCmdBreakAfter >(); - bOk &= Register< CMICmdCmdBreakCondition >(); - bOk &= Register< CMICmdCmdBreakDelete >(); - bOk &= Register< CMICmdCmdBreakDisable >(); - bOk &= Register< CMICmdCmdBreakEnable >(); - bOk &= Register< CMICmdCmdBreakInsert >(); - bOk &= Register< CMICmdCmdDataDisassemble >(); - bOk &= Register< CMICmdCmdDataEvaluateExpression >(); - bOk &= Register< CMICmdCmdDataReadMemoryBytes >(); - bOk &= Register< CMICmdCmdDataReadMemory >(); - bOk &= Register< CMICmdCmdDataListRegisterNames >(); - bOk &= Register< CMICmdCmdDataListRegisterValues >(); - bOk &= Register< CMICmdCmdDataWriteMemory >(); - bOk &= Register< CMICmdCmdEnablePrettyPrinting >(); - bOk &= Register< CMICmdCmdEnvironmentCd >(); - bOk &= Register< CMICmdCmdExecContinue >(); - bOk &= Register< CMICmdCmdExecInterrupt >(); - bOk &= Register< CMICmdCmdExecFinish >(); - bOk &= Register< CMICmdCmdExecNext >(); - bOk &= Register< CMICmdCmdExecNextInstruction >(); - bOk &= Register< CMICmdCmdExecRun >(); - bOk &= Register< CMICmdCmdExecStep >(); - bOk &= Register< CMICmdCmdExecStepInstruction >(); - bOk &= Register< CMICmdCmdFileExecAndSymbols >(); - bOk &= Register< CMICmdCmdGdbExit >(); - bOk &= Register< CMICmdCmdGdbInfo >(); - bOk &= Register< CMICmdCmdGdbSet >(); - bOk &= Register< CMICmdCmdGdbThread >(); - bOk &= Register< CMICmdCmdInferiorTtySet >(); - bOk &= Register< CMICmdCmdInterpreterExec >(); - bOk &= Register< CMICmdCmdListThreadGroups >(); - bOk &= Register< CMICmdCmdSource >(); - bOk &= Register< CMICmdCmdStackInfoDepth >(); - bOk &= Register< CMICmdCmdStackListFrames >(); - bOk &= Register< CMICmdCmdStackListArguments >(); - bOk &= Register< CMICmdCmdStackListLocals >(); - bOk &= Register< CMICmdCmdSupportListFeatures >(); - bOk &= Register< CMICmdCmdTargetSelect >(); - bOk &= Register< CMICmdCmdThreadInfo >(); - bOk &= Register< CMICmdCmdVarAssign >(); - bOk &= Register< CMICmdCmdVarCreate >(); - bOk &= Register< CMICmdCmdVarDelete >(); - bOk &= Register< CMICmdCmdVarEvaluateExpression >(); - bOk &= Register< CMICmdCmdVarInfoPathExpression >(); - bOk &= Register< CMICmdCmdVarListChildren >(); - bOk &= Register< CMICmdCmdVarSetFormat >(); - bOk &= Register< CMICmdCmdVarShowAttributes >(); - bOk &= Register< CMICmdCmdVarUpdate >(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); + bOk &= Register(); - return bOk; + return bOk; } diff --git a/tools/lldb-mi/MICmdCommands.h b/tools/lldb-mi/MICmdCommands.h index 7bfc8aef6867..0e9d27714302 100644 --- a/tools/lldb-mi/MICmdCommands.h +++ b/tools/lldb-mi/MICmdCommands.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdCommands.h +// File: MICmdCommands.h // -// Overview: CMICmdCommands instantiated. +// Overview: CMICmdCommands instantiated. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -25,12 +25,11 @@ namespace MICmnCommands { //++ ============================================================================ -// Details: MI Command are instantiated and registered automatically with the -// Command Factory -// Gotchas: None. -// Authors: Illya Rudkin 18/02/2014. -// Changes: None. +// Details: MI Command are instantiated and registered automatically with the +// Command Factory +// Gotchas: None. +// Authors: Illya Rudkin 18/02/2014. +// Changes: None. //-- -bool RegisterAll( void ); - +bool RegisterAll(void); } diff --git a/tools/lldb-mi/MICmdData.cpp b/tools/lldb-mi/MICmdData.cpp index 8eb84f32000a..44aa3c25dcb8 100644 --- a/tools/lldb-mi/MICmdData.cpp +++ b/tools/lldb-mi/MICmdData.cpp @@ -8,17 +8,16 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdData.cpp +// File: MICmdData.cpp // -// Overview: SMICmdData implementation. +// Overview: SMICmdData implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: #include "MICmdData.h" - diff --git a/tools/lldb-mi/MICmdData.h b/tools/lldb-mi/MICmdData.h index d54a21663581..114e32b26336 100644 --- a/tools/lldb-mi/MICmdData.h +++ b/tools/lldb-mi/MICmdData.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdData.h +// File: MICmdData.h // -// Overview: SMICmdData interface. +// Overview: SMICmdData interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -25,50 +25,49 @@ #include "MICmnResources.h" //++ ============================================================================ -// Details: MI command metadata. Holds the command's name, MI number and options -// as found on stdin. Holds the command's MI output (written to stdout). -// Gotchas: None. -// Authors: Illya Rudkin 18/02/2014. -// Changes: None. +// Details: MI command metadata. Holds the command's name, MI number and options +// as found on stdin. Holds the command's MI output (written to stdout). +// Gotchas: None. +// Authors: Illya Rudkin 18/02/2014. +// Changes: None. //-- struct SMICmdData { - SMICmdData( void ) - : id( 0 ) - , bCmdValid( false ) - , bCmdExecutedSuccessfully( false ) - , bMIOldStyle( false ) - , bHasResultRecordExtra( false ) - { - }; + SMICmdData(void) + : id(0) + , bCmdValid(false) + , bCmdExecutedSuccessfully(false) + , bMIOldStyle(false) + , bHasResultRecordExtra(false){}; - MIuint id; // A command's unique ID i.e. GUID - CMIUtilString strMiCmdToken; // The command's MI token (a number) - CMIUtilString strMiCmd; // The command's name - CMIUtilString strMiCmdOption; // The command's arguments or options - CMIUtilString strMiCmdAll; // The text as received from the client - CMIUtilString strMiCmdResultRecord; // Each command forms 1 response to its input - CMIUtilString strMiCmdResultRecordExtra; // Hack command produce more response text to help the client because of using LLDB - bool bCmdValid; // True = Valid MI format command, false = invalid - bool bCmdExecutedSuccessfully; // True = Command finished successfully, false = Did not start/did not complete - CMIUtilString strErrorDescription; // Command failed this is why - bool bMIOldStyle; // True = format "3thread", false = format "3-thread" - bool bHasResultRecordExtra; // True = Yes command produced additional MI output to its 1 line response, false = no extra MI output formed + MIuint id; // A command's unique ID i.e. GUID + CMIUtilString strMiCmdToken; // The command's MI token (a number) + CMIUtilString strMiCmd; // The command's name + CMIUtilString strMiCmdOption; // The command's arguments or options + CMIUtilString strMiCmdAll; // The text as received from the client + CMIUtilString strMiCmdResultRecord; // Each command forms 1 response to its input + CMIUtilString strMiCmdResultRecordExtra; // Hack command produce more response text to help the client because of using LLDB + bool bCmdValid; // True = Valid MI format command, false = invalid + bool bCmdExecutedSuccessfully; // True = Command finished successfully, false = Did not start/did not complete + CMIUtilString strErrorDescription; // Command failed this is why + bool bMIOldStyle; // True = format "3thread", false = format "3-thread" + bool + bHasResultRecordExtra; // True = Yes command produced additional MI output to its 1 line response, false = no extra MI output formed - void Clear( void ) - { - id = 0; - strMiCmdToken.clear(); - strMiCmd = MIRSRC( IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION ); - strMiCmdOption.clear(); - strMiCmdAll.clear(); - strMiCmdResultRecord.clear(); - strMiCmdResultRecordExtra.clear(); - bCmdValid = false; - bCmdExecutedSuccessfully = false; - strErrorDescription.clear(); - bMIOldStyle = false; - bHasResultRecordExtra = false; - } + void + Clear(void) + { + id = 0; + strMiCmdToken.clear(); + strMiCmd = MIRSRC(IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION); + strMiCmdOption.clear(); + strMiCmdAll.clear(); + strMiCmdResultRecord.clear(); + strMiCmdResultRecordExtra.clear(); + bCmdValid = false; + bCmdExecutedSuccessfully = false; + strErrorDescription.clear(); + bMIOldStyle = false; + bHasResultRecordExtra = false; + } }; - diff --git a/tools/lldb-mi/MICmdFactory.cpp b/tools/lldb-mi/MICmdFactory.cpp index 4897c60e4d66..ba333e7e1d0d 100644 --- a/tools/lldb-mi/MICmdFactory.cpp +++ b/tools/lldb-mi/MICmdFactory.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdFactory.cpp +// File: MICmdFactory.cpp // -// Overview: CMICmdFactory implementation. +// Overview: CMICmdFactory implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -27,203 +27,211 @@ #include "MICmdCommands.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdFactory constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdFactory constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdFactory::CMICmdFactory( void ) +CMICmdFactory::CMICmdFactory(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdFactory destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdFactory destructor. +// Type: Overridable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdFactory::~CMICmdFactory( void ) +CMICmdFactory::~CMICmdFactory(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this Command factory. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Initialize resources for *this Command factory. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmdFactory::Initialize( void ) +bool +CMICmdFactory::Initialize(void) { - m_clientUsageRefCnt++; + m_clientUsageRefCnt++; - if( m_bInitialized ) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - m_bInitialized = true; + m_bInitialized = true; - MICmnCommands::RegisterAll(); + MICmnCommands::RegisterAll(); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this Command Factory. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Release resources for *this Command Factory. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmdFactory::Shutdown( void ) +bool +CMICmdFactory::Shutdown(void) { - if( --m_clientUsageRefCnt > 0 ) - return MIstatus::success; - - if( !m_bInitialized ) - return MIstatus::success; + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - m_mapMiCmdToCmdCreatorFn.clear(); + if (!m_bInitialized) + return MIstatus::success; - m_bInitialized = false; + m_mapMiCmdToCmdCreatorFn.clear(); - return MIstatus::success; -} + m_bInitialized = false; + + return MIstatus::success; +} //++ ------------------------------------------------------------------------------------ -// Details: Register a command's creator function with the command identitier the MI -// command name i.e. 'file-exec-and-symbols'. -// Type: Method. -// Args: vMiCmd - (R) Command's name, the MI command. -// vCmdCreateFn - (R) Command's creator function pointer. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Register a command's creator function with the command identitier the MI +// command name i.e. 'file-exec-and-symbols'. +// Type: Method. +// Args: vMiCmd - (R) Command's name, the MI command. +// vCmdCreateFn - (R) Command's creator function pointer. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmdFactory::CmdRegister( const CMIUtilString & vMiCmd, CmdCreatorFnPtr vCmdCreateFn ) +bool +CMICmdFactory::CmdRegister(const CMIUtilString &vMiCmd, CmdCreatorFnPtr vCmdCreateFn) { - if( !IsValid( vMiCmd ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMDFACTORY_ERR_INVALID_CMD_NAME ), vMiCmd.c_str() ) ); - return MIstatus::failure; - } - if( vCmdCreateFn == nullptr ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN ), vMiCmd.c_str() ) ); - return MIstatus::failure; - } - - if( HaveAlready( vMiCmd ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED ), vMiCmd.c_str() ) ); - return MIstatus::failure; - } - - MapPairMiCmdToCmdCreatorFn_t pr( vMiCmd, vCmdCreateFn ); - m_mapMiCmdToCmdCreatorFn.insert( pr ); - - return MIstatus::success; + if (!IsValid(vMiCmd)) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMDFACTORY_ERR_INVALID_CMD_NAME), vMiCmd.c_str())); + return MIstatus::failure; + } + if (vCmdCreateFn == nullptr) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN), vMiCmd.c_str())); + return MIstatus::failure; + } + + if (HaveAlready(vMiCmd)) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED), vMiCmd.c_str())); + return MIstatus::failure; + } + + MapPairMiCmdToCmdCreatorFn_t pr(vMiCmd, vCmdCreateFn); + m_mapMiCmdToCmdCreatorFn.insert(pr); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Check a command is already registered. -// Type: Method. -// Args: vMiCmd - (R) Command's name, the MI command. -// Return: True - registered. -// False - not found. -// Throws: None. +// Details: Check a command is already registered. +// Type: Method. +// Args: vMiCmd - (R) Command's name, the MI command. +// Return: True - registered. +// False - not found. +// Throws: None. //-- -bool CMICmdFactory::HaveAlready( const CMIUtilString & vMiCmd ) const +bool +CMICmdFactory::HaveAlready(const CMIUtilString &vMiCmd) const { - const MapMiCmdToCmdCreatorFn_t::const_iterator it = m_mapMiCmdToCmdCreatorFn.find( vMiCmd ); - if( it != m_mapMiCmdToCmdCreatorFn.end() ) - return true; - - return false; + const MapMiCmdToCmdCreatorFn_t::const_iterator it = m_mapMiCmdToCmdCreatorFn.find(vMiCmd); + if (it != m_mapMiCmdToCmdCreatorFn.end()) + return true; + + return false; } //++ ------------------------------------------------------------------------------------ -// Details: Check a command's name is valid: -// - name is not empty -// - name does not have spaces -// Type: Method. -// Args: vMiCmd - (R) Command's name, the MI command. -// Return: True - valid. -// False - not valid. -// Throws: None. +// Details: Check a command's name is valid: +// - name is not empty +// - name does not have spaces +// Type: Method. +// Args: vMiCmd - (R) Command's name, the MI command. +// Return: True - valid. +// False - not valid. +// Throws: None. //-- -bool CMICmdFactory::IsValid( const CMIUtilString & vMiCmd ) const +bool +CMICmdFactory::IsValid(const CMIUtilString &vMiCmd) const { - bool bValid = true; - - if( vMiCmd.empty() ) - { - bValid = false; - return false; - } - - const MIint nPos = vMiCmd.find( " " ); - if( nPos != (MIint) std::string::npos ) - bValid = false; - - return bValid; + bool bValid = true; + + if (vMiCmd.empty()) + { + bValid = false; + return false; + } + + const MIint nPos = vMiCmd.find(" "); + if (nPos != (MIint)std::string::npos) + bValid = false; + + return bValid; } //++ ------------------------------------------------------------------------------------ -// Details: Check a command is already registered. -// Type: Method. -// Args: vMiCmd - (R) Command's name, the MI command. -// Return: True - registered. -// False - not found. -// Throws: None. +// Details: Check a command is already registered. +// Type: Method. +// Args: vMiCmd - (R) Command's name, the MI command. +// Return: True - registered. +// False - not found. +// Throws: None. //-- -bool CMICmdFactory::CmdExist( const CMIUtilString & vMiCmd ) const +bool +CMICmdFactory::CmdExist(const CMIUtilString &vMiCmd) const { - return HaveAlready( vMiCmd ); + return HaveAlready(vMiCmd); } //++ ------------------------------------------------------------------------------------ -// Details: Create a command given the specified MI command name. The command data object -// contains the options for the command. -// Type: Method. -// Args: vMiCmd - (R) Command's name, the MI command. -// vCmdData - (RW) Command's metadata status/information/result object. -// vpNewCmd - (W) New command instance. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Create a command given the specified MI command name. The command data object +// contains the options for the command. +// Type: Method. +// Args: vMiCmd - (R) Command's name, the MI command. +// vCmdData - (RW) Command's metadata status/information/result object. +// vpNewCmd - (W) New command instance. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmdFactory::CmdCreate( const CMIUtilString & vMiCmd, const SMICmdData & vCmdData, CMICmdBase *& vpNewCmd ) +bool +CMICmdFactory::CmdCreate(const CMIUtilString &vMiCmd, const SMICmdData &vCmdData, CMICmdBase *&vpNewCmd) { - bool bOk = MIstatus::success; - - vpNewCmd = nullptr; - - if( !IsValid( vMiCmd ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMDFACTORY_ERR_INVALID_CMD_NAME ), vMiCmd.c_str() ) ); - return MIstatus::failure; - } - if( !HaveAlready( vMiCmd ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED ), vMiCmd.c_str() ) ); - return MIstatus::failure; - } - - const MapMiCmdToCmdCreatorFn_t::const_iterator it = m_mapMiCmdToCmdCreatorFn.find( vMiCmd ); - const CMIUtilString & rMiCmd( (*it).first ); MIunused( rMiCmd ); - CmdCreatorFnPtr pFn = (*it).second; - CMICmdBase * pCmd = (*pFn)(); - - SMICmdData cmdData( vCmdData ); - cmdData.id = pCmd->GetGUID(); - bOk = pCmd->SetCmdData( cmdData ); - if( bOk ) - vpNewCmd = pCmd; - - return bOk; + bool bOk = MIstatus::success; + + vpNewCmd = nullptr; + + if (!IsValid(vMiCmd)) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMDFACTORY_ERR_INVALID_CMD_NAME), vMiCmd.c_str())); + return MIstatus::failure; + } + if (!HaveAlready(vMiCmd)) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED), vMiCmd.c_str())); + return MIstatus::failure; + } + + const MapMiCmdToCmdCreatorFn_t::const_iterator it = m_mapMiCmdToCmdCreatorFn.find(vMiCmd); + const CMIUtilString &rMiCmd((*it).first); + MIunused(rMiCmd); + CmdCreatorFnPtr pFn = (*it).second; + CMICmdBase *pCmd = (*pFn)(); + + SMICmdData cmdData(vCmdData); + cmdData.id = pCmd->GetGUID(); + bOk = pCmd->SetCmdData(cmdData); + if (bOk) + vpNewCmd = pCmd; + + return bOk; } diff --git a/tools/lldb-mi/MICmdFactory.h b/tools/lldb-mi/MICmdFactory.h index 52281d1e7d1d..7af4b34ad0e7 100644 --- a/tools/lldb-mi/MICmdFactory.h +++ b/tools/lldb-mi/MICmdFactory.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdFactory.h +// File: MICmdFactory.h // -// Overview: CMICmdFactory interface. +// Overview: CMICmdFactory interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -33,67 +33,66 @@ class CMICmdBase; struct SMICmdData; //++ ============================================================================ -// Details: MI Command Factory. Holds a list of registered MI commands that -// MI application understands to interpret. Creates commands objects. -// The Command Factory is carried out in the main thread. -// A singleton class. -// Gotchas: None. -// Authors: Illya Rudkin 19/02/2014. -// Changes: None. +// Details: MI Command Factory. Holds a list of registered MI commands that +// MI application understands to interpret. Creates commands objects. +// The Command Factory is carried out in the main thread. +// A singleton class. +// Gotchas: None. +// Authors: Illya Rudkin 19/02/2014. +// Changes: None. //-- -class CMICmdFactory -: public CMICmnBase -, public MI::ISingleton< CMICmdFactory > +class CMICmdFactory : public CMICmnBase, public MI::ISingleton { - friend class MI::ISingleton< CMICmdFactory >; + friend class MI::ISingleton; -// Typedefs: -public: - typedef CMICmdBase * (*CmdCreatorFnPtr)( void ); + // Typedefs: + public: + typedef CMICmdBase *(*CmdCreatorFnPtr)(void); -// Class: -public: - //++ - // Description: Command's factory's interface for commands to implement. - //-- - class ICmd - { - public: - virtual const CMIUtilString & GetMiCmd( void ) const = 0; - virtual CmdCreatorFnPtr GetCmdCreatorFn( void ) const = 0; - //virtual CMICmdBase * CreateSelf( void ) = 0; // Not possible as require a static creator function in the command class, here for awareness + // Class: + public: + //++ + // Description: Command's factory's interface for commands to implement. + //-- + class ICmd + { + public: + virtual const CMIUtilString &GetMiCmd(void) const = 0; + virtual CmdCreatorFnPtr GetCmdCreatorFn(void) const = 0; + // virtual CMICmdBase * CreateSelf( void ) = 0; // Not possible as require a static creator + // function in the command class, here for awareness - /* dtor */ virtual ~ICmd( void ) {}; - }; + /* dtor */ virtual ~ICmd(void){}; + }; -// Methods: -public: - bool Initialize( void ); - bool Shutdown( void ); - bool CmdRegister( const CMIUtilString & vMiCmd, CmdCreatorFnPtr vCmdCreateFn ); - bool CmdCreate( const CMIUtilString & vMiCmd, const SMICmdData & vCmdData, CMICmdBase *& vpNewCmd ); - bool CmdExist( const CMIUtilString & vMiCmd ) const; + // Methods: + public: + bool Initialize(void); + bool Shutdown(void); + bool CmdRegister(const CMIUtilString &vMiCmd, CmdCreatorFnPtr vCmdCreateFn); + bool CmdCreate(const CMIUtilString &vMiCmd, const SMICmdData &vCmdData, CMICmdBase *&vpNewCmd); + bool CmdExist(const CMIUtilString &vMiCmd) const; -// Methods: -private: - /* ctor */ CMICmdFactory( void ); - /* ctor */ CMICmdFactory( const CMICmdFactory & ); - void operator=( const CMICmdFactory & ); - - bool HaveAlready( const CMIUtilString & vMiCmd ) const; - bool IsValid( const CMIUtilString & vMiCmd ) const; + // Methods: + private: + /* ctor */ CMICmdFactory(void); + /* ctor */ CMICmdFactory(const CMICmdFactory &); + void operator=(const CMICmdFactory &); -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMICmdFactory( void ); + bool HaveAlready(const CMIUtilString &vMiCmd) const; + bool IsValid(const CMIUtilString &vMiCmd) const; -// Typedefs: -private: - typedef std::map< CMIUtilString, CmdCreatorFnPtr > MapMiCmdToCmdCreatorFn_t; - typedef std::pair< CMIUtilString, CmdCreatorFnPtr > MapPairMiCmdToCmdCreatorFn_t; + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMICmdFactory(void); -// Attributes: -private: - MapMiCmdToCmdCreatorFn_t m_mapMiCmdToCmdCreatorFn; + // Typedefs: + private: + typedef std::map MapMiCmdToCmdCreatorFn_t; + typedef std::pair MapPairMiCmdToCmdCreatorFn_t; + + // Attributes: + private: + MapMiCmdToCmdCreatorFn_t m_mapMiCmdToCmdCreatorFn; }; diff --git a/tools/lldb-mi/MICmdInterpreter.cpp b/tools/lldb-mi/MICmdInterpreter.cpp index dd5b2818705c..33db4b8196df 100644 --- a/tools/lldb-mi/MICmdInterpreter.cpp +++ b/tools/lldb-mi/MICmdInterpreter.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdInterpreter.cpp +// File: MICmdInterpreter.cpp // -// Overview: CMICmdInterpreter implementation. +// Overview: CMICmdInterpreter implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -24,278 +24,286 @@ #include "MICmdFactory.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdInterpreter constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdInterpreter constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdInterpreter::CMICmdInterpreter( void ) -: m_rCmdFactory( CMICmdFactory::Instance() ) +CMICmdInterpreter::CMICmdInterpreter(void) + : m_rCmdFactory(CMICmdFactory::Instance()) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdInterpreter destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdInterpreter destructor. +// Type: Overridable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdInterpreter::~CMICmdInterpreter( void ) +CMICmdInterpreter::~CMICmdInterpreter(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this Command Interpreter. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialize resources for *this Command Interpreter. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdInterpreter::Initialize( void ) +bool +CMICmdInterpreter::Initialize(void) { - m_clientUsageRefCnt++; + m_clientUsageRefCnt++; - if( m_bInitialized ) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - m_bInitialized = true; + m_bInitialized = true; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this Command Interpreter. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Release resources for *this Command Interpreter. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdInterpreter::Shutdown( void ) +bool +CMICmdInterpreter::Shutdown(void) { - if( --m_clientUsageRefCnt > 0 ) - return MIstatus::success; - - if( !m_bInitialized ) - return MIstatus::success; + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - m_bInitialized = false; + if (!m_bInitialized) + return MIstatus::success; - return MIstatus::success; -} + m_bInitialized = false; + + return MIstatus::success; +} //++ ------------------------------------------------------------------------------------ -// Details: Establish whether the text data is an MI format type command. -// Type: Method. -// Args: vTextLine - (R) Text data to interpret. -// vwbYesValid - (W) True = MI type command, false = not recognised. -// vwbCmdNotInCmdFactor - (W) True = MI command not found in the command factory, false = recognised. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Establish whether the text data is an MI format type command. +// Type: Method. +// Args: vTextLine - (R) Text data to interpret. +// vwbYesValid - (W) True = MI type command, false = not recognised. +// vwbCmdNotInCmdFactor - (W) True = MI command not found in the command factory, false = recognised. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdInterpreter::ValidateIsMi( const CMIUtilString & vTextLine, bool & vwbYesValid, bool & vwbCmdNotInCmdFactor, SMICmdData & rwCmdData ) +bool +CMICmdInterpreter::ValidateIsMi(const CMIUtilString &vTextLine, bool &vwbYesValid, bool &vwbCmdNotInCmdFactor, SMICmdData &rwCmdData) { - vwbYesValid = false; - vwbCmdNotInCmdFactor = false; - rwCmdData.Clear(); + vwbYesValid = false; + vwbCmdNotInCmdFactor = false; + rwCmdData.Clear(); - if( vTextLine.empty() ) - return MIstatus::success; + if (vTextLine.empty()) + return MIstatus::success; - // MI format is [cmd #]-[command name][command arg(s)] - // i.e. 1-file-exec-and-symbols --thread-group i1 DEVICE_EXECUTABLE - // 5-data-evaluate-expression --thread 1 --frame 0 *(argv) + // MI format is [cmd #]-[command name][command arg(s)] + // i.e. 1-file-exec-and-symbols --thread-group i1 DEVICE_EXECUTABLE + // 5-data-evaluate-expression --thread 1 --frame 0 *(argv) - m_miCmdData.Clear(); - m_miCmdData.strMiCmd = vTextLine; + m_miCmdData.Clear(); + m_miCmdData.strMiCmd = vTextLine; - // The following change m_miCmdData as valid parts are indentified - vwbYesValid = (MiHasCmdTokenEndingHypthen( vTextLine ) || MiHasCmdTokenEndingAlpha( vTextLine )); - vwbYesValid = vwbYesValid && MiHasCmd( vTextLine ); - if( vwbYesValid ) - { - vwbCmdNotInCmdFactor = !HasCmdFactoryGotMiCmd( MiGetCmdData() ); - vwbYesValid = !vwbCmdNotInCmdFactor; - } + // The following change m_miCmdData as valid parts are indentified + vwbYesValid = (MiHasCmdTokenEndingHypthen(vTextLine) || MiHasCmdTokenEndingAlpha(vTextLine)); + vwbYesValid = vwbYesValid && MiHasCmd(vTextLine); + if (vwbYesValid) + { + vwbCmdNotInCmdFactor = !HasCmdFactoryGotMiCmd(MiGetCmdData()); + vwbYesValid = !vwbCmdNotInCmdFactor; + } - // Update command's meta data valid state - m_miCmdData.bCmdValid = vwbYesValid; + // Update command's meta data valid state + m_miCmdData.bCmdValid = vwbYesValid; - // Ok to return new updated command information - rwCmdData = MiGetCmdData(); + // Ok to return new updated command information + rwCmdData = MiGetCmdData(); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Establish whether the command name entered on the stdin stream is recognised by -// the MI driver. -// Type: Method. -// Args: vCmd - (R) Command information structure. -// Return: bool - True = yes command is recognised, false = command not recognised. -// Throws: None. +// Details: Establish whether the command name entered on the stdin stream is recognised by +// the MI driver. +// Type: Method. +// Args: vCmd - (R) Command information structure. +// Return: bool - True = yes command is recognised, false = command not recognised. +// Throws: None. //-- -bool CMICmdInterpreter::HasCmdFactoryGotMiCmd( const SMICmdData & vCmd ) const +bool +CMICmdInterpreter::HasCmdFactoryGotMiCmd(const SMICmdData &vCmd) const { - return m_rCmdFactory.CmdExist( vCmd.strMiCmd ); + return m_rCmdFactory.CmdExist(vCmd.strMiCmd); } //++ ------------------------------------------------------------------------------------ -// Details: Does the command entered match the criteria for a MI command format. -// The format to validate against is 'nn-' where there can be 1 to n digits. -// I.e. '2-gdb-exit'. -// Is the execution token present? The command token is entered into the -// command meta data structure whether correct or not for reporting or later -// command execution purposes. -// Type: Method. -// Args: vTextLine - (R) Text data to interpret. -// Return: bool - True = yes command token present, false = command not recognised. -// Throws: None. +// Details: Does the command entered match the criteria for a MI command format. +// The format to validate against is 'nn-' where there can be 1 to n digits. +// I.e. '2-gdb-exit'. +// Is the execution token present? The command token is entered into the +// command meta data structure whether correct or not for reporting or later +// command execution purposes. +// Type: Method. +// Args: vTextLine - (R) Text data to interpret. +// Return: bool - True = yes command token present, false = command not recognised. +// Throws: None. //-- -bool CMICmdInterpreter::MiHasCmdTokenEndingHypthen( const CMIUtilString & vTextLine ) +bool +CMICmdInterpreter::MiHasCmdTokenEndingHypthen(const CMIUtilString &vTextLine) { - // The hythen is mandatory - const MIint nPos = vTextLine.find( "-", 0 ); - if( (nPos == (MIint) std::string::npos) ) - return false; - - if( MiHasCmdTokenPresent( vTextLine ) ) - { - const std::string strNum = vTextLine.substr( 0, nPos ); - if( !CMIUtilString( strNum.c_str() ).IsNumber() ) - return false; - - m_miCmdData.strMiCmdToken = strNum.c_str(); - } - - m_miCmdData.bMIOldStyle = false; - - return true; + // The hythen is mandatory + const MIint nPos = vTextLine.find("-", 0); + if ((nPos == (MIint)std::string::npos)) + return false; + + if (MiHasCmdTokenPresent(vTextLine)) + { + const std::string strNum = vTextLine.substr(0, nPos); + if (!CMIUtilString(strNum.c_str()).IsNumber()) + return false; + + m_miCmdData.strMiCmdToken = strNum.c_str(); + } + + m_miCmdData.bMIOldStyle = false; + + return true; } //++ ------------------------------------------------------------------------------------ -// Details: Does the command entered match the criteria for a MI command format. -// The format to validate against is 'nnA' where there can be 1 to n digits. -// 'A' represents any non numeric token. I.e. '1source .gdbinit'. -// Is the execution token present? The command token is entered into the -// command meta data structure whether correct or not for reporting or later -// command execution purposes. -// Type: Method. -// Args: vTextLine - (R) Text data to interpret. -// Return: bool - True = yes command token present, false = command not recognised. -// Throws: None. +// Details: Does the command entered match the criteria for a MI command format. +// The format to validate against is 'nnA' where there can be 1 to n digits. +// 'A' represents any non numeric token. I.e. '1source .gdbinit'. +// Is the execution token present? The command token is entered into the +// command meta data structure whether correct or not for reporting or later +// command execution purposes. +// Type: Method. +// Args: vTextLine - (R) Text data to interpret. +// Return: bool - True = yes command token present, false = command not recognised. +// Throws: None. //-- -bool CMICmdInterpreter::MiHasCmdTokenEndingAlpha( const CMIUtilString & vTextLine ) +bool +CMICmdInterpreter::MiHasCmdTokenEndingAlpha(const CMIUtilString &vTextLine) { - MIchar cChar = vTextLine[ 0 ]; - MIuint i = 0; - while( ::isdigit( cChar ) != 0 ) - { - cChar = vTextLine[ ++i ]; - } - if( ::isalpha( cChar ) == 0 ) - return false; - if( i == 0 ) - return false; - - const std::string strNum = vTextLine.substr( 0, i ); - m_miCmdData.strMiCmdToken = strNum.c_str(); - m_miCmdData.bMIOldStyle = true; - - return true; + MIchar cChar = vTextLine[0]; + MIuint i = 0; + while (::isdigit(cChar) != 0) + { + cChar = vTextLine[++i]; + } + if (::isalpha(cChar) == 0) + return false; + if (i == 0) + return false; + + const std::string strNum = vTextLine.substr(0, i); + m_miCmdData.strMiCmdToken = strNum.c_str(); + m_miCmdData.bMIOldStyle = true; + + return true; } //++ ------------------------------------------------------------------------------------ -// Details: Does the command entered match the criteria for a MI command format. -// Is the command token present before the hypen? -// Type: Method. -// Args: vTextLine - (R) Text data to interpret. -// Return: bool - True = yes command token present, false = token not present. -// Throws: None. +// Details: Does the command entered match the criteria for a MI command format. +// Is the command token present before the hypen? +// Type: Method. +// Args: vTextLine - (R) Text data to interpret. +// Return: bool - True = yes command token present, false = token not present. +// Throws: None. //-- -bool CMICmdInterpreter::MiHasCmdTokenPresent( const CMIUtilString & vTextLine ) +bool +CMICmdInterpreter::MiHasCmdTokenPresent(const CMIUtilString &vTextLine) { - const MIint nPos = vTextLine.find( "-", 0 ); - return (nPos > 0); + const MIint nPos = vTextLine.find("-", 0); + return (nPos > 0); } //++ ------------------------------------------------------------------------------------ -// Details: Does the command name entered match the criteria for a MI command format. -// Is a recogised command present? The command name is entered into the -// command meta data structure whether correct or not for reporting or later -// command execution purposes. Command options is present are also put into the -// command meta data structure. -// Type: Method. -// Args: vTextLine - (R) Command information structure. -// Return: bool - True = yes command name present, false = command not recognised. -// Throws: None. +// Details: Does the command name entered match the criteria for a MI command format. +// Is a recogised command present? The command name is entered into the +// command meta data structure whether correct or not for reporting or later +// command execution purposes. Command options is present are also put into the +// command meta data structure. +// Type: Method. +// Args: vTextLine - (R) Command information structure. +// Return: bool - True = yes command name present, false = command not recognised. +// Throws: None. //-- -bool CMICmdInterpreter::MiHasCmd( const CMIUtilString & vTextLine ) +bool +CMICmdInterpreter::MiHasCmd(const CMIUtilString &vTextLine) { - MIint nPos = 0; - if( m_miCmdData.bMIOldStyle ) - { - char cChar = vTextLine[ 0 ]; - MIuint i = 0; - while( ::isdigit( cChar ) != 0 ) - { - cChar = vTextLine[ ++i ]; - } - nPos = --i; - } - else - { - nPos = vTextLine.find( "-", 0 ); - } - - bool bFoundCmd = false; - const MIint nLen = vTextLine.length(); - const MIint nPos2 = vTextLine.find( " ", nPos ); - if( nPos2 != (MIint) std::string::npos ) - { - if( nPos2 == nLen ) - return false; - const CMIUtilString cmd = CMIUtilString( vTextLine.substr( nPos + 1, nPos2 - nPos - 1 ).c_str() ); - if( cmd.empty() ) - return false; - - m_miCmdData.strMiCmd = cmd; - - if( nPos2 < nLen ) - m_miCmdData.strMiCmdOption = CMIUtilString( vTextLine.substr( nPos2 + 1, nLen - nPos2 - 1 ).c_str() ); - - bFoundCmd = true; - } - else - { - const CMIUtilString cmd = CMIUtilString( vTextLine.substr( nPos + 1, nLen - nPos - 1 ).c_str() ); - if( cmd.empty() ) - return false; - m_miCmdData.strMiCmd = cmd; - bFoundCmd = true; - } - - if( bFoundCmd ) - m_miCmdData.strMiCmdAll = vTextLine; - - return bFoundCmd; + MIint nPos = 0; + if (m_miCmdData.bMIOldStyle) + { + char cChar = vTextLine[0]; + MIuint i = 0; + while (::isdigit(cChar) != 0) + { + cChar = vTextLine[++i]; + } + nPos = --i; + } + else + { + nPos = vTextLine.find("-", 0); + } + + bool bFoundCmd = false; + const MIint nLen = vTextLine.length(); + const MIint nPos2 = vTextLine.find(" ", nPos); + if (nPos2 != (MIint)std::string::npos) + { + if (nPos2 == nLen) + return false; + const CMIUtilString cmd = CMIUtilString(vTextLine.substr(nPos + 1, nPos2 - nPos - 1).c_str()); + if (cmd.empty()) + return false; + + m_miCmdData.strMiCmd = cmd; + + if (nPos2 < nLen) + m_miCmdData.strMiCmdOption = CMIUtilString(vTextLine.substr(nPos2 + 1, nLen - nPos2 - 1).c_str()); + + bFoundCmd = true; + } + else + { + const CMIUtilString cmd = CMIUtilString(vTextLine.substr(nPos + 1, nLen - nPos - 1).c_str()); + if (cmd.empty()) + return false; + m_miCmdData.strMiCmd = cmd; + bFoundCmd = true; + } + + if (bFoundCmd) + m_miCmdData.strMiCmdAll = vTextLine; + + return bFoundCmd; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the just entered new command from stdin. It contains the command -// name, number and any options. -// Type: Method. -// Args: vTextLine - (R) Command information structure. -// Return: SMICmdData & - Command meta data information/result/status. -// Throws: None. +// Details: Retrieve the just entered new command from stdin. It contains the command +// name, number and any options. +// Type: Method. +// Args: vTextLine - (R) Command information structure. +// Return: SMICmdData & - Command meta data information/result/status. +// Throws: None. //-- -const SMICmdData & CMICmdInterpreter::MiGetCmdData( void ) const +const SMICmdData & +CMICmdInterpreter::MiGetCmdData(void) const { - return m_miCmdData; + return m_miCmdData; } - diff --git a/tools/lldb-mi/MICmdInterpreter.h b/tools/lldb-mi/MICmdInterpreter.h index d924a1f77af2..cc06179de882 100644 --- a/tools/lldb-mi/MICmdInterpreter.h +++ b/tools/lldb-mi/MICmdInterpreter.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdInterpreter.h +// File: MICmdInterpreter.h // -// Overview: CMICmdInterpreter interface. +// Overview: CMICmdInterpreter interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -30,49 +30,47 @@ class CMICmdFactory; //++ ============================================================================ -// Details: MI command interpreter. It takes text data from the MI driver -// (which got it from Stdin singleton) and validate the text to see if -// matches Machine Interface (MI) format and commands defined in the -// MI application. -// A singleton class. -// Gotchas: None. -// Authors: Illya Rudkin 18/02/2014. -// Changes: None. +// Details: MI command interpreter. It takes text data from the MI driver +// (which got it from Stdin singleton) and validate the text to see if +// matches Machine Interface (MI) format and commands defined in the +// MI application. +// A singleton class. +// Gotchas: None. +// Authors: Illya Rudkin 18/02/2014. +// Changes: None. //-- -class CMICmdInterpreter -: public CMICmnBase -, public MI::ISingleton< CMICmdInterpreter > +class CMICmdInterpreter : public CMICmnBase, public MI::ISingleton { - friend MI::ISingleton< CMICmdInterpreter >; + friend MI::ISingleton; -// Methods: -public: -// Methods: -public: - bool Initialize( void ); - bool Shutdown( void ); - bool ValidateIsMi( const CMIUtilString & vTextLine, bool & vwbYesValid, bool & vwbCmdNotInCmdFactor, SMICmdData & rwCmdData ); + // Methods: + public: + // Methods: + public: + bool Initialize(void); + bool Shutdown(void); + bool ValidateIsMi(const CMIUtilString &vTextLine, bool &vwbYesValid, bool &vwbCmdNotInCmdFactor, SMICmdData &rwCmdData); -// Methods: -private: - /* ctor */ CMICmdInterpreter( void ); - /* ctor */ CMICmdInterpreter( const CMICmdInterpreter & ); - void operator=( const CMICmdInterpreter & ); - - bool HasCmdFactoryGotMiCmd( const SMICmdData & vCmdData ) const; - bool MiHasCmdTokenEndingHypthen( const CMIUtilString & vTextLine ); - bool MiHasCmdTokenEndingAlpha( const CMIUtilString & vTextLine ); - bool MiHasCmd( const CMIUtilString & vTextLine ); - bool MiHasCmdTokenPresent( const CMIUtilString & vTextLine ); - const SMICmdData & MiGetCmdData() const; + // Methods: + private: + /* ctor */ CMICmdInterpreter(void); + /* ctor */ CMICmdInterpreter(const CMICmdInterpreter &); + void operator=(const CMICmdInterpreter &); -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMICmdInterpreter( void ); + bool HasCmdFactoryGotMiCmd(const SMICmdData &vCmdData) const; + bool MiHasCmdTokenEndingHypthen(const CMIUtilString &vTextLine); + bool MiHasCmdTokenEndingAlpha(const CMIUtilString &vTextLine); + bool MiHasCmd(const CMIUtilString &vTextLine); + bool MiHasCmdTokenPresent(const CMIUtilString &vTextLine); + const SMICmdData &MiGetCmdData() const; -// Attributes: -private: - SMICmdData m_miCmdData; // Filled in on each new line being interpreted - CMICmdFactory & m_rCmdFactory; + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMICmdInterpreter(void); + + // Attributes: + private: + SMICmdData m_miCmdData; // Filled in on each new line being interpreted + CMICmdFactory &m_rCmdFactory; }; diff --git a/tools/lldb-mi/MICmdInvoker.cpp b/tools/lldb-mi/MICmdInvoker.cpp index 41f9f77542a3..c415fbaf18b5 100644 --- a/tools/lldb-mi/MICmdInvoker.cpp +++ b/tools/lldb-mi/MICmdInvoker.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdInvoker.cpp +// File: MICmdInvoker.cpp // -// Overview: CMICmdInvoker implementation. +// Overview: CMICmdInvoker implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -28,306 +28,318 @@ #include "MIDriver.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdInvoker constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdInvoker constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdInvoker::CMICmdInvoker( void ) -: m_rStreamOut( CMICmnStreamStdout::Instance() ) +CMICmdInvoker::CMICmdInvoker(void) + : m_rStreamOut(CMICmnStreamStdout::Instance()) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdInvoker destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdInvoker destructor. +// Type: Overridable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdInvoker::~CMICmdInvoker( void ) +CMICmdInvoker::~CMICmdInvoker(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this Command Invoker. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialize resources for *this Command Invoker. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdInvoker::Initialize( void ) +bool +CMICmdInvoker::Initialize(void) { - m_clientUsageRefCnt++; + m_clientUsageRefCnt++; - if( m_bInitialized ) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - m_bInitialized = true; + m_bInitialized = true; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this Stdin stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Release resources for *this Stdin stream. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdInvoker::Shutdown( void ) +bool +CMICmdInvoker::Shutdown(void) { - if( --m_clientUsageRefCnt > 0 ) - return MIstatus::success; - - if( !m_bInitialized ) - return MIstatus::success; + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - CmdDeleteAll(); + if (!m_bInitialized) + return MIstatus::success; - m_bInitialized = false; + CmdDeleteAll(); - return MIstatus::success; -} + m_bInitialized = false; + + return MIstatus::success; +} //++ ------------------------------------------------------------------------------------ -// Details: Empty the map of invoked commands doing work. Command objects are deleted too. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: Empty the map of invoked commands doing work. Command objects are deleted too. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMICmdInvoker::CmdDeleteAll( void ) +void +CMICmdInvoker::CmdDeleteAll(void) { - CMICmdMgr & rMgr = CMICmdMgr::Instance(); - MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.begin(); - while( it != m_mapCmdIdToCmd.end() ) - { - const MIuint cmdId( (*it).first ); MIunused( cmdId ); - CMICmdBase * pCmd = (*it).second; - const CMIUtilString & rCmdName( pCmd->GetCmdData().strMiCmd ); MIunused( rCmdName ); - rMgr.CmdDelete( pCmd->GetCmdData() ); - - // Next - ++it; - } - m_mapCmdIdToCmd.clear(); + CMICmdMgr &rMgr = CMICmdMgr::Instance(); + MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.begin(); + while (it != m_mapCmdIdToCmd.end()) + { + const MIuint cmdId((*it).first); + MIunused(cmdId); + CMICmdBase *pCmd = (*it).second; + const CMIUtilString &rCmdName(pCmd->GetCmdData().strMiCmd); + MIunused(rCmdName); + rMgr.CmdDelete(pCmd->GetCmdData()); + + // Next + ++it; + } + m_mapCmdIdToCmd.clear(); } //++ ------------------------------------------------------------------------------------ -// Details: Remove from the map of invoked commands doing work a command that has finished -// its work. The command object is deleted too. -// Type: Method. -// Args: vId - (R) Command object's unique ID. -// vbYesDeleteCmd - (R) True = Delete command object, false = delete via the Command Manager. -// Return: None. -// Throws: None. +// Details: Remove from the map of invoked commands doing work a command that has finished +// its work. The command object is deleted too. +// Type: Method. +// Args: vId - (R) Command object's unique ID. +// vbYesDeleteCmd - (R) True = Delete command object, false = delete via the Command Manager. +// Return: None. +// Throws: None. //-- -bool CMICmdInvoker::CmdDelete( const MIuint vId, const bool vbYesDeleteCmd /*= false*/ ) +bool +CMICmdInvoker::CmdDelete(const MIuint vId, const bool vbYesDeleteCmd /*= false*/) { - CMICmdMgr & rMgr = CMICmdMgr::Instance(); - MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.find( vId ); - if( it != m_mapCmdIdToCmd.end() ) - { - CMICmdBase * pCmd = (*it).second; - if( vbYesDeleteCmd ) - { - // Via registered interest command manager callback *this object to delete the command - m_mapCmdIdToCmd.erase( it ); - delete pCmd; - } - else - // Notify other interested object of this command's pending deletion - rMgr.CmdDelete( pCmd->GetCmdData() ); - } - - if( m_mapCmdIdToCmd.empty() ) - rMgr.CmdUnregisterForDeleteNotification( *this ); - - return MIstatus::success; + CMICmdMgr &rMgr = CMICmdMgr::Instance(); + MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.find(vId); + if (it != m_mapCmdIdToCmd.end()) + { + CMICmdBase *pCmd = (*it).second; + if (vbYesDeleteCmd) + { + // Via registered interest command manager callback *this object to delete the command + m_mapCmdIdToCmd.erase(it); + delete pCmd; + } + else + // Notify other interested object of this command's pending deletion + rMgr.CmdDelete(pCmd->GetCmdData()); + } + + if (m_mapCmdIdToCmd.empty()) + rMgr.CmdUnregisterForDeleteNotification(*this); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Add to the map of invoked commands doing work a command that is about to -// start to do work. -// Type: Method. -// Args: vCmd - (R) Command object. -// Return: None. -// Throws: None. +// Details: Add to the map of invoked commands doing work a command that is about to +// start to do work. +// Type: Method. +// Args: vCmd - (R) Command object. +// Return: None. +// Throws: None. //-- -bool CMICmdInvoker::CmdAdd( const CMICmdBase & vCmd ) +bool +CMICmdInvoker::CmdAdd(const CMICmdBase &vCmd) { - if( m_mapCmdIdToCmd.empty() ) - { - CMICmdMgr & rMgr = CMICmdMgr::Instance(); - rMgr.CmdRegisterForDeleteNotification( *this ); - } + if (m_mapCmdIdToCmd.empty()) + { + CMICmdMgr &rMgr = CMICmdMgr::Instance(); + rMgr.CmdRegisterForDeleteNotification(*this); + } - const MIuint & cmdId( vCmd.GetCmdData().id ); - MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.find( cmdId ); - if( it != m_mapCmdIdToCmd.end() ) - return MIstatus::success; + const MIuint &cmdId(vCmd.GetCmdData().id); + MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.find(cmdId); + if (it != m_mapCmdIdToCmd.end()) + return MIstatus::success; - MapPairCmdIdToCmd_t pr( cmdId, const_cast< CMICmdBase *>( &vCmd )); - m_mapCmdIdToCmd.insert( pr ); + MapPairCmdIdToCmd_t pr(cmdId, const_cast(&vCmd)); + m_mapCmdIdToCmd.insert(pr); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Having previously had the potential command validated and found valid now -// get the command executed. -// If the Functionalityity returns MIstatus::failure call GetErrorDescription(). -// This function is used by the application's main thread. -// Type: Method. -// Args: vCmd - (RW) Command object. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Having previously had the potential command validated and found valid now +// get the command executed. +// If the Functionalityity returns MIstatus::failure call GetErrorDescription(). +// This function is used by the application's main thread. +// Type: Method. +// Args: vCmd - (RW) Command object. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmdInvoker::CmdExecute( CMICmdBase & vCmd ) +bool +CMICmdInvoker::CmdExecute(CMICmdBase &vCmd) { - bool bOk = CmdAdd( vCmd ); - - if( bOk && !vCmd.ParseArgs() ) - { - // Report command execution failed - const SMICmdData cmdData( vCmd.GetCmdData() ); - CmdStdout( cmdData ); - CmdCauseAppExit( vCmd ); - CmdDelete( cmdData.id ); - - // Proceed to wait or execute next command - return MIstatus::success; - } - - if( bOk && !vCmd.Execute() ) - { - // Report command execution failed - const SMICmdData cmdData( vCmd.GetCmdData() ); - CmdStdout( cmdData ); - CmdCauseAppExit( vCmd ); - CmdDelete( cmdData.id ); - - // Proceed to wait or execute next command - return MIstatus::success; - } - - bOk = CmdExecuteFinished( vCmd ); - - return bOk; + bool bOk = CmdAdd(vCmd); + + if (bOk && !vCmd.ParseArgs()) + { + // Report command execution failed + const SMICmdData cmdData(vCmd.GetCmdData()); + CmdStdout(cmdData); + CmdCauseAppExit(vCmd); + CmdDelete(cmdData.id); + + // Proceed to wait or execute next command + return MIstatus::success; + } + + if (bOk && !vCmd.Execute()) + { + // Report command execution failed + const SMICmdData cmdData(vCmd.GetCmdData()); + CmdStdout(cmdData); + CmdCauseAppExit(vCmd); + CmdDelete(cmdData.id); + + // Proceed to wait or execute next command + return MIstatus::success; + } + + bOk = CmdExecuteFinished(vCmd); + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Called when a command has finished its Execution() work either synchronously -// because the command executed was the type a non event type or asynchronoulsy -// via the command's callback (because of an SB Listener event). Needs to be called -// so that *this invoker call do some house keeping and then proceed to call -// the command's Acknowledge() function. -// Type: Method. -// Args: vCmd - (R) Command object. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Called when a command has finished its Execution() work either synchronously +// because the command executed was the type a non event type or asynchronoulsy +// via the command's callback (because of an SB Listener event). Needs to be called +// so that *this invoker call do some house keeping and then proceed to call +// the command's Acknowledge() function. +// Type: Method. +// Args: vCmd - (R) Command object. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmdInvoker::CmdExecuteFinished( CMICmdBase & vCmd ) +bool +CMICmdInvoker::CmdExecuteFinished(CMICmdBase &vCmd) { - // Command finished now get the command to gather it's information and form the MI - // Result record - if( !vCmd.Acknowledge() ) - { - // Report command acknowledge functionality failed - const SMICmdData cmdData( vCmd.GetCmdData() ); - CmdStdout( cmdData ); - CmdCauseAppExit( vCmd ); - CmdDelete( cmdData.id ); - - // Proceed to wait or execute next command - return MIstatus::success; - } - - // Retrieve the command's latest data/information. Needed for commands of the event type so have - // a record of commands pending finishing execution. - const CMIUtilString & rMIResultRecord( vCmd.GetMIResultRecord() ); - SMICmdData cmdData( vCmd.GetCmdData() ); // Make a copy as the command will be deleted soon - cmdData.strMiCmdResultRecord = rMIResultRecord; // Precautionary copy as the command might forget to do this - if( vCmd.HasMIResultRecordExtra() ) - { - cmdData.bHasResultRecordExtra = true; - const CMIUtilString & rMIExtra( vCmd.GetMIResultRecordExtra() ); - cmdData.strMiCmdResultRecordExtra = rMIExtra; // Precautionary copy as the command might forget to do this - } - - // Send command's MI response to the client - bool bOk = CmdStdout( cmdData ); - - // Delete the command object as do not require anymore - bOk = bOk && CmdDelete( vCmd.GetCmdData().id ); - - return bOk; + // Command finished now get the command to gather it's information and form the MI + // Result record + if (!vCmd.Acknowledge()) + { + // Report command acknowledge functionality failed + const SMICmdData cmdData(vCmd.GetCmdData()); + CmdStdout(cmdData); + CmdCauseAppExit(vCmd); + CmdDelete(cmdData.id); + + // Proceed to wait or execute next command + return MIstatus::success; + } + + // Retrieve the command's latest data/information. Needed for commands of the event type so have + // a record of commands pending finishing execution. + const CMIUtilString &rMIResultRecord(vCmd.GetMIResultRecord()); + SMICmdData cmdData(vCmd.GetCmdData()); // Make a copy as the command will be deleted soon + cmdData.strMiCmdResultRecord = rMIResultRecord; // Precautionary copy as the command might forget to do this + if (vCmd.HasMIResultRecordExtra()) + { + cmdData.bHasResultRecordExtra = true; + const CMIUtilString &rMIExtra(vCmd.GetMIResultRecordExtra()); + cmdData.strMiCmdResultRecordExtra = rMIExtra; // Precautionary copy as the command might forget to do this + } + + // Send command's MI response to the client + bool bOk = CmdStdout(cmdData); + + // Delete the command object as do not require anymore + bOk = bOk && CmdDelete(vCmd.GetCmdData().id); + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: If the MI Driver is not operating via a client i.e. Eclipse check the command -// on failure suggests the application exits. A command can be such that a -// failure cannot the allow the application to continue operating. -// Args: vCmd - (R) Command object. -// Return: None. -// Return: None. -// Throws: None. +// Details: If the MI Driver is not operating via a client i.e. Eclipse check the command +// on failure suggests the application exits. A command can be such that a +// failure cannot the allow the application to continue operating. +// Args: vCmd - (R) Command object. +// Return: None. +// Return: None. +// Throws: None. //-- -void CMICmdInvoker::CmdCauseAppExit( const CMICmdBase & vCmd ) const +void +CMICmdInvoker::CmdCauseAppExit(const CMICmdBase &vCmd) const { - if( vCmd.GetExitAppOnCommandFailure() ) - { - CMIDriver & rDriver( CMIDriver::Instance() ); - if( rDriver.IsDriverDebuggingArgExecutable() ) - { - rDriver.SetExitApplicationFlag( true ); - } - } + if (vCmd.GetExitAppOnCommandFailure()) + { + CMIDriver &rDriver(CMIDriver::Instance()); + if (rDriver.IsDriverDebuggingArgExecutable()) + { + rDriver.SetExitApplicationFlag(true); + } + } } //++ ------------------------------------------------------------------------------------ -// Details: Write to stdout and the Log file the command's MI formatted result. -// Type: vCmdData - (R) A command's information. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Return: None. -// Throws: None. +// Details: Write to stdout and the Log file the command's MI formatted result. +// Type: vCmdData - (R) A command's information. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Return: None. +// Throws: None. //-- -bool CMICmdInvoker::CmdStdout( const SMICmdData & vCmdData ) const +bool +CMICmdInvoker::CmdStdout(const SMICmdData &vCmdData) const { - bool bOk = m_pLog->WriteLog( vCmdData.strMiCmdAll ); - const bool bLock = bOk && m_rStreamOut.Lock(); - bOk = bOk && bLock && m_rStreamOut.WriteMIResponse( vCmdData.strMiCmdResultRecord ); - if( bOk && vCmdData.bHasResultRecordExtra ) - { - bOk = m_rStreamOut.WriteMIResponse( vCmdData.strMiCmdResultRecordExtra ); - } - bOk = bLock && m_rStreamOut.Unlock(); - - return bOk; + bool bOk = m_pLog->WriteLog(vCmdData.strMiCmdAll); + const bool bLock = bOk && m_rStreamOut.Lock(); + bOk = bOk && bLock && m_rStreamOut.WriteMIResponse(vCmdData.strMiCmdResultRecord); + if (bOk && vCmdData.bHasResultRecordExtra) + { + bOk = m_rStreamOut.WriteMIResponse(vCmdData.strMiCmdResultRecordExtra); + } + bOk = bLock && m_rStreamOut.Unlock(); + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdMgr::ICmdDeleteCallback. *this object is registered -// with the Command Manager to receive callbacks when a command is being deleted. -// An object, *this invoker, does not delete a command object itself but calls -// the Command Manager to delete a command object. This function is the Invoker's -// called. -// The Invoker owns the command objects and so can delete them but must do it -// via the manager so other objects can be notified of the deletion. -// Type: Method. -// Args: vCmd - (RW) Command. -// Return: None. -// Throws: None. +// Details: Required by the CMICmdMgr::ICmdDeleteCallback. *this object is registered +// with the Command Manager to receive callbacks when a command is being deleted. +// An object, *this invoker, does not delete a command object itself but calls +// the Command Manager to delete a command object. This function is the Invoker's +// called. +// The Invoker owns the command objects and so can delete them but must do it +// via the manager so other objects can be notified of the deletion. +// Type: Method. +// Args: vCmd - (RW) Command. +// Return: None. +// Throws: None. //-- -void CMICmdInvoker::Delete( SMICmdData & vCmd ) +void +CMICmdInvoker::Delete(SMICmdData &vCmd) { - CmdDelete( vCmd.id, true ); + CmdDelete(vCmd.id, true); } diff --git a/tools/lldb-mi/MICmdInvoker.h b/tools/lldb-mi/MICmdInvoker.h index b89d506b1f58..09c20c909240 100644 --- a/tools/lldb-mi/MICmdInvoker.h +++ b/tools/lldb-mi/MICmdInvoker.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdInvoker.h +// File: MICmdInvoker.h // -// Overview: CMICmdInvoker interface. +// Overview: CMICmdInvoker interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -35,84 +35,81 @@ class CMICmdBase; class CMICmnStreamStdout; //++ ============================================================================ -// Details: MI Command Invoker. The Invoker works on the command pattern design. -// There two main jobs; action command Execute() function, followed by -// the command's Acknowledge() function. When a command has finished its -// execute function it returns to the invoker. The invoker then calls the -// command's Acknowledge() function to do more work, form and give -// back a MI result. In the meantime the Command Monitor is monitoring -// the each command doing their Execute() function work so they do not -// exceed a time limit which if it exceeds informs the command(s) to -// stop work. -// The work by the Invoker is carried out in the main thread. -// The Invoker takes ownersip of any commands created which means it -// is the only object to delete them when a command is finished working. -// A singleton class. -// Gotchas: None. -// Authors: Illya Rudkin 19/02/2014. -// Changes: None. +// Details: MI Command Invoker. The Invoker works on the command pattern design. +// There two main jobs; action command Execute() function, followed by +// the command's Acknowledge() function. When a command has finished its +// execute function it returns to the invoker. The invoker then calls the +// command's Acknowledge() function to do more work, form and give +// back a MI result. In the meantime the Command Monitor is monitoring +// the each command doing their Execute() function work so they do not +// exceed a time limit which if it exceeds informs the command(s) to +// stop work. +// The work by the Invoker is carried out in the main thread. +// The Invoker takes ownersip of any commands created which means it +// is the only object to delete them when a command is finished working. +// A singleton class. +// Gotchas: None. +// Authors: Illya Rudkin 19/02/2014. +// Changes: None. //-- -class CMICmdInvoker -: public CMICmnBase -, public CMICmdMgrSetCmdDeleteCallback::ICallback -, public MI::ISingleton< CMICmdInvoker > +class CMICmdInvoker : public CMICmnBase, public CMICmdMgrSetCmdDeleteCallback::ICallback, public MI::ISingleton { - friend class MI::ISingleton< CMICmdInvoker >; + friend class MI::ISingleton; -// Class: -public: - //++ - // Description: Invoker's interface for commands to implement. - //-- - class ICmd - { - public: - virtual bool Acknowledge( void ) = 0; - virtual bool Execute( void ) = 0; - virtual bool ParseArgs( void ) = 0; - virtual bool SetCmdData( const SMICmdData & vCmdData ) = 0; - virtual const SMICmdData & GetCmdData( void ) const = 0; - virtual const CMIUtilString & GetErrorDescription( void ) const = 0; - virtual void CmdFinishedTellInvoker( void ) const = 0; - virtual const CMIUtilString & GetMIResultRecord( void ) const = 0; - virtual const CMIUtilString & GetMIResultRecordExtra( void ) const = 0; - virtual bool HasMIResultRecordExtra( void ) const = 0; + // Class: + public: + //++ + // Description: Invoker's interface for commands to implement. + //-- + class ICmd + { + public: + virtual bool Acknowledge(void) = 0; + virtual bool Execute(void) = 0; + virtual bool ParseArgs(void) = 0; + virtual bool SetCmdData(const SMICmdData &vCmdData) = 0; + virtual const SMICmdData &GetCmdData(void) const = 0; + virtual const CMIUtilString &GetErrorDescription(void) const = 0; + virtual void CmdFinishedTellInvoker(void) const = 0; + virtual const CMIUtilString &GetMIResultRecord(void) const = 0; + virtual const CMIUtilString &GetMIResultRecordExtra(void) const = 0; + virtual bool HasMIResultRecordExtra(void) const = 0; - /* dtor */ virtual ~ICmd( void ) {}; - }; - -// Methods: -public: - bool Initialize( void ); - bool Shutdown( void ); - bool CmdExecute( CMICmdBase & vCmd ); - bool CmdExecuteFinished( CMICmdBase & vCmd ); + /* dtor */ virtual ~ICmd(void){}; + }; -// Typedefs: -private: - typedef std::map< MIuint, CMICmdBase * > MapCmdIdToCmd_t; - typedef std::pair< MIuint, CMICmdBase * > MapPairCmdIdToCmd_t; + // Methods: + public: + bool Initialize(void); + bool Shutdown(void); + bool CmdExecute(CMICmdBase &vCmd); + bool CmdExecuteFinished(CMICmdBase &vCmd); -// Methods: -private: - /* ctor */ CMICmdInvoker( void ); - /* ctor */ CMICmdInvoker( const CMICmdInvoker & ); - void operator=( const CMICmdInvoker & ); - void CmdDeleteAll( void ); - bool CmdDelete( const MIuint vCmdId, const bool vbYesDeleteCmd = false ); - bool CmdAdd( const CMICmdBase & vCmd ); - bool CmdStdout( const SMICmdData & vCmdData ) const; - void CmdCauseAppExit( const CMICmdBase & vCmd ) const; - -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMICmdInvoker( void ); - // From CMICmdMgrSetCmdDeleteCallback::ICallback - virtual void Delete( SMICmdData & vCmd ); + // Typedefs: + private: + typedef std::map MapCmdIdToCmd_t; + typedef std::pair MapPairCmdIdToCmd_t; -// Attributes: -private: - MapCmdIdToCmd_t m_mapCmdIdToCmd; - CMICmnStreamStdout & m_rStreamOut; + // Methods: + private: + /* ctor */ CMICmdInvoker(void); + /* ctor */ CMICmdInvoker(const CMICmdInvoker &); + void operator=(const CMICmdInvoker &); + void CmdDeleteAll(void); + bool CmdDelete(const MIuint vCmdId, const bool vbYesDeleteCmd = false); + bool CmdAdd(const CMICmdBase &vCmd); + bool CmdStdout(const SMICmdData &vCmdData) const; + void CmdCauseAppExit(const CMICmdBase &vCmd) const; + + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMICmdInvoker(void); + // From CMICmdMgrSetCmdDeleteCallback::ICallback + virtual void Delete(SMICmdData &vCmd); + + // Attributes: + private: + MapCmdIdToCmd_t m_mapCmdIdToCmd; + CMICmnStreamStdout &m_rStreamOut; }; diff --git a/tools/lldb-mi/MICmdMgr.cpp b/tools/lldb-mi/MICmdMgr.cpp index 4abcbad3f48d..44778b55daf0 100644 --- a/tools/lldb-mi/MICmdMgr.cpp +++ b/tools/lldb-mi/MICmdMgr.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdMgr.cpp +// File: MICmdMgr.cpp // -// Overview: CMICmdMgr implementation. +// Overview: CMICmdMgr implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -31,227 +31,237 @@ #include "MIUtilSingletonHelper.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmdMgr constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdMgr constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdMgr::CMICmdMgr( void ) -: m_interpretor( CMICmdInterpreter::Instance() ) -, m_factory( CMICmdFactory::Instance() ) -, m_invoker( CMICmdInvoker::Instance() ) +CMICmdMgr::CMICmdMgr(void) + : m_interpretor(CMICmdInterpreter::Instance()) + , m_factory(CMICmdFactory::Instance()) + , m_invoker(CMICmdInvoker::Instance()) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmdMgr destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmdMgr destructor. +// Type: Overridable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmdMgr::~CMICmdMgr( void ) +CMICmdMgr::~CMICmdMgr(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this Command Manager. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Initialize resources for *this Command Manager. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmdMgr::Initialize( void ) +bool +CMICmdMgr::Initialize(void) { - m_clientUsageRefCnt++; + m_clientUsageRefCnt++; - if( m_bInitialized ) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Note initialization order is important here as some resources depend on previous - MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); - MI::ModuleInit< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg ); - if( bOk && !m_interpretor.Initialize() ) - { - bOk = false; - errMsg = CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_CMDINTERPRETER ), m_interpretor.GetErrorDescription().c_str() ); - } - if( bOk && !m_factory.Initialize() ) - { - bOk = false; - errMsg = CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_CMDFACTORY ), m_factory.GetErrorDescription().c_str() ); - } - if( bOk && !m_invoker.Initialize() ) - { - bOk = false; - errMsg = CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_CMDINVOKER ), m_invoker.GetErrorDescription().c_str() ); - } - m_bInitialized = bOk; + bool bOk = MIstatus::success; + CMIUtilString errMsg; - if( !bOk ) - { - CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_CMDMGR ), errMsg.c_str() ) ); - SetErrorDescription( strInitError ); - return MIstatus::failure; - } + // Note initialization order is important here as some resources depend on previous + MI::ModuleInit(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + if (bOk && !m_interpretor.Initialize()) + { + bOk = false; + errMsg = CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_CMDINTERPRETER), m_interpretor.GetErrorDescription().c_str()); + } + if (bOk && !m_factory.Initialize()) + { + bOk = false; + errMsg = CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_CMDFACTORY), m_factory.GetErrorDescription().c_str()); + } + if (bOk && !m_invoker.Initialize()) + { + bOk = false; + errMsg = CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_CMDINVOKER), m_invoker.GetErrorDescription().c_str()); + } + m_bInitialized = bOk; - return MIstatus::success; + if (!bOk) + { + CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_CMDMGR), errMsg.c_str())); + SetErrorDescription(strInitError); + return MIstatus::failure; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this Command Manager. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Release resources for *this Command Manager. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmdMgr::Shutdown( void ) +bool +CMICmdMgr::Shutdown(void) { - if( --m_clientUsageRefCnt > 0 ) - return MIstatus::success; - - if( !m_bInitialized ) - return MIstatus::success; + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; + + if (!m_bInitialized) + return MIstatus::success; - m_bInitialized = false; + m_bInitialized = false; - ClrErrorDescription(); + ClrErrorDescription(); - bool bOk = MIstatus::success; - CMIUtilString errMsg; + bool bOk = MIstatus::success; + CMIUtilString errMsg; - // Tidy up - m_setCmdDeleteCallback.clear(); + // Tidy up + m_setCmdDeleteCallback.clear(); - // Note shutdown order is important here - if( !m_invoker.Shutdown() ) - { - bOk = false; - errMsg += CMIUtilString::Format( MIRSRC( IDS_MI_SHTDWN_ERR_CMDINVOKER ), m_invoker.GetErrorDescription().c_str() ); - } - if( !m_factory.Shutdown() ) - { - bOk = false; - if( !errMsg.empty() ) errMsg += ", "; - errMsg += CMIUtilString::Format( MIRSRC( IDS_MI_SHTDWN_ERR_CMDFACTORY ), m_factory.GetErrorDescription().c_str() ); - } - if( !m_interpretor.Shutdown() ) - { - bOk = false; - if( !errMsg.empty() ) errMsg += ", "; - errMsg += CMIUtilString::Format( MIRSRC( IDS_MI_SHTDWN_ERR_CMDINTERPRETER ), m_interpretor.GetErrorDescription().c_str() ); - } - MI::ModuleShutdown< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg ); - MI::ModuleShutdown< CMICmnLog >( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); + // Note shutdown order is important here + if (!m_invoker.Shutdown()) + { + bOk = false; + errMsg += CMIUtilString::Format(MIRSRC(IDS_MI_SHTDWN_ERR_CMDINVOKER), m_invoker.GetErrorDescription().c_str()); + } + if (!m_factory.Shutdown()) + { + bOk = false; + if (!errMsg.empty()) + errMsg += ", "; + errMsg += CMIUtilString::Format(MIRSRC(IDS_MI_SHTDWN_ERR_CMDFACTORY), m_factory.GetErrorDescription().c_str()); + } + if (!m_interpretor.Shutdown()) + { + bOk = false; + if (!errMsg.empty()) + errMsg += ", "; + errMsg += CMIUtilString::Format(MIRSRC(IDS_MI_SHTDWN_ERR_CMDINTERPRETER), m_interpretor.GetErrorDescription().c_str()); + } + MI::ModuleShutdown(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - if( !bOk ) - { - SetErrorDescriptionn( MIRSRC( IDS_MI_SHUTDOWN_ERR ), errMsg.c_str() ); - } + if (!bOk) + { + SetErrorDescriptionn(MIRSRC(IDS_MI_SHUTDOWN_ERR), errMsg.c_str()); + } - return MIstatus::success; -} + return MIstatus::success; +} //++ ------------------------------------------------------------------------------------ -// Details: Establish whether the text data is an MI format type command. -// Type: Method. -// Args: vTextLine - (R) Text data to interpret. -// vwbYesValid - (W) True = MI type command, false = not recognised. -// vwbCmdNotInCmdFactor - (W) True = MI command not found in the command factor, false = recognised. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Establish whether the text data is an MI format type command. +// Type: Method. +// Args: vTextLine - (R) Text data to interpret. +// vwbYesValid - (W) True = MI type command, false = not recognised. +// vwbCmdNotInCmdFactor - (W) True = MI command not found in the command factor, false = recognised. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmdMgr::CmdInterpret( const CMIUtilString & vTextLine, bool & vwbYesValid, bool & vwbCmdNotInCmdFactor, SMICmdData & rwCmdData ) +bool +CMICmdMgr::CmdInterpret(const CMIUtilString &vTextLine, bool &vwbYesValid, bool &vwbCmdNotInCmdFactor, SMICmdData &rwCmdData) { - return m_interpretor.ValidateIsMi( vTextLine, vwbYesValid, vwbCmdNotInCmdFactor, rwCmdData ); + return m_interpretor.ValidateIsMi(vTextLine, vwbYesValid, vwbCmdNotInCmdFactor, rwCmdData); } //++ ------------------------------------------------------------------------------------ -// Details: Having previously had the potential command validated and found valid now -// get the command executed. -// If the Functionalityity returns MIstatus::failure call GetErrorDescription(). -// This function is used by the application's main thread. -// Type: Method. -// Args: vCmdData - (RW) Command meta data. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Having previously had the potential command validated and found valid now +// get the command executed. +// If the Functionalityity returns MIstatus::failure call GetErrorDescription(). +// This function is used by the application's main thread. +// Type: Method. +// Args: vCmdData - (RW) Command meta data. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmdMgr::CmdExecute( const SMICmdData & vCmdData ) +bool +CMICmdMgr::CmdExecute(const SMICmdData &vCmdData) { - bool bOk = MIstatus::success; - - // Pass the command's meta data structure to the command - // so it can update it if required. (Need to copy it out of the - // command before the command is deleted) - CMICmdBase * pCmd = nullptr; - bOk = m_factory.CmdCreate( vCmdData.strMiCmd, vCmdData, pCmd ); - if( !bOk ) - { - const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_CMDMGR_ERR_CMD_FAILED_CREATE ), m_factory.GetErrorDescription().c_str() ) ); - SetErrorDescription( errMsg ); - return MIstatus::failure; - } + bool bOk = MIstatus::success; + + // Pass the command's meta data structure to the command + // so it can update it if required. (Need to copy it out of the + // command before the command is deleted) + CMICmdBase *pCmd = nullptr; + bOk = m_factory.CmdCreate(vCmdData.strMiCmd, vCmdData, pCmd); + if (!bOk) + { + const CMIUtilString errMsg( + CMIUtilString::Format(MIRSRC(IDS_CMDMGR_ERR_CMD_FAILED_CREATE), m_factory.GetErrorDescription().c_str())); + SetErrorDescription(errMsg); + return MIstatus::failure; + } + + bOk = m_invoker.CmdExecute(*pCmd); + if (!bOk) + { + const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_CMDMGR_ERR_CMD_INVOKER), m_invoker.GetErrorDescription().c_str())); + SetErrorDescription(errMsg); + return MIstatus::failure; + } - bOk = m_invoker.CmdExecute( *pCmd ); - if( !bOk ) - { - const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_CMDMGR_ERR_CMD_INVOKER ), m_invoker.GetErrorDescription().c_str() ) ); - SetErrorDescription( errMsg ); - return MIstatus::failure; - } - - return bOk; + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Iterate all interested clients and tell them a command is being deleted. -// Type: Method. -// Args: vCmdData - (RW) The command to be deleted. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Iterate all interested clients and tell them a command is being deleted. +// Type: Method. +// Args: vCmdData - (RW) The command to be deleted. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdMgr::CmdDelete( SMICmdData vCmdData ) +bool +CMICmdMgr::CmdDelete(SMICmdData vCmdData) { - // Note vCmdData is a copy! The command holding its copy will be deleted soon - // we still need to iterate callback clients after a command object is deleted + // Note vCmdData is a copy! The command holding its copy will be deleted soon + // we still need to iterate callback clients after a command object is deleted - m_setCmdDeleteCallback.Delete( vCmdData ); + m_setCmdDeleteCallback.Delete(vCmdData); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Register an object to be called when a command object is deleted. -// Type: Method. -// Args: vObject - (R) A new interested client. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Register an object to be called when a command object is deleted. +// Type: Method. +// Args: vObject - (R) A new interested client. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdMgr::CmdRegisterForDeleteNotification( CMICmdMgrSetCmdDeleteCallback::ICallback & vObject ) +bool +CMICmdMgr::CmdRegisterForDeleteNotification(CMICmdMgrSetCmdDeleteCallback::ICallback &vObject) { - return m_setCmdDeleteCallback.Register( vObject ); + return m_setCmdDeleteCallback.Register(vObject); } //++ ------------------------------------------------------------------------------------ -// Details: Unregister an object from being called when a command object is deleted. -// Type: Method. -// Args: vObject - (R) The was interested client. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Unregister an object from being called when a command object is deleted. +// Type: Method. +// Args: vObject - (R) The was interested client. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmdMgr::CmdUnregisterForDeleteNotification( CMICmdMgrSetCmdDeleteCallback::ICallback & vObject ) +bool +CMICmdMgr::CmdUnregisterForDeleteNotification(CMICmdMgrSetCmdDeleteCallback::ICallback &vObject) { - return m_setCmdDeleteCallback.Unregister( vObject ); + return m_setCmdDeleteCallback.Unregister(vObject); } diff --git a/tools/lldb-mi/MICmdMgr.h b/tools/lldb-mi/MICmdMgr.h index 2b6a99248b16..f403e1778c96 100644 --- a/tools/lldb-mi/MICmdMgr.h +++ b/tools/lldb-mi/MICmdMgr.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdMgr.h +// File: MICmdMgr.h // -// Overview: CMICmdMgr interface. +// Overview: CMICmdMgr interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -33,51 +33,49 @@ // Declarations: class CMICmdInterpreter; class CMICmdFactory; -class CMICmdInvoker; +class CMICmdInvoker; class CMICmdBase; //++ ============================================================================ -// Details: MI command manager. Oversees command operations, controls command -// production and the running of commands. -// Command Invoker, Command Factory and Command Monitor while independant -// units are overseen/managed by *this manager. -// A singleton class. -// Gotchas: None. -// Authors: Illya Rudkin 19/02/2014. -// Changes: None. +// Details: MI command manager. Oversees command operations, controls command +// production and the running of commands. +// Command Invoker, Command Factory and Command Monitor while independant +// units are overseen/managed by *this manager. +// A singleton class. +// Gotchas: None. +// Authors: Illya Rudkin 19/02/2014. +// Changes: None. //-- -class CMICmdMgr -: public CMICmnBase -, public MI::ISingleton< CMICmdMgr > +class CMICmdMgr : public CMICmnBase, public MI::ISingleton { - friend class MI::ISingleton< CMICmdMgr >; + friend class MI::ISingleton; -// Methods: -public: - bool Initialize( void ); - bool Shutdown( void ); - - bool CmdInterpret( const CMIUtilString & vTextLine, bool & vwbYesValid, bool & vwbCmdNotInCmdFactor, SMICmdData & rwCmdData ); - bool CmdExecute( const SMICmdData & vCmdData ); - bool CmdDelete( SMICmdData vCmdData ); - bool CmdRegisterForDeleteNotification( CMICmdMgrSetCmdDeleteCallback::ICallback & vObject ); - bool CmdUnregisterForDeleteNotification( CMICmdMgrSetCmdDeleteCallback::ICallback & vObject ); + // Methods: + public: + bool Initialize(void); + bool Shutdown(void); -// Methods: -private: - /* ctor */ CMICmdMgr( void ); - /* ctor */ CMICmdMgr( const CMICmdMgr & ); - void operator=( const CMICmdMgr & ); - -// Overridden: -public: - // From CMICmnBase - /* dtor */ virtual ~CMICmdMgr( void ); + bool CmdInterpret(const CMIUtilString &vTextLine, bool &vwbYesValid, bool &vwbCmdNotInCmdFactor, SMICmdData &rwCmdData); + bool CmdExecute(const SMICmdData &vCmdData); + bool CmdDelete(SMICmdData vCmdData); + bool CmdRegisterForDeleteNotification(CMICmdMgrSetCmdDeleteCallback::ICallback &vObject); + bool CmdUnregisterForDeleteNotification(CMICmdMgrSetCmdDeleteCallback::ICallback &vObject); -// Attributes: -private: - CMICmdInterpreter & m_interpretor; - CMICmdFactory & m_factory; - CMICmdInvoker & m_invoker; - CMICmdMgrSetCmdDeleteCallback::CSetClients m_setCmdDeleteCallback; -}; \ No newline at end of file + // Methods: + private: + /* ctor */ CMICmdMgr(void); + /* ctor */ CMICmdMgr(const CMICmdMgr &); + void operator=(const CMICmdMgr &); + + // Overridden: + public: + // From CMICmnBase + /* dtor */ virtual ~CMICmdMgr(void); + + // Attributes: + private: + CMICmdInterpreter &m_interpretor; + CMICmdFactory &m_factory; + CMICmdInvoker &m_invoker; + CMICmdMgrSetCmdDeleteCallback::CSetClients m_setCmdDeleteCallback; +}; diff --git a/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp b/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp index 1303a8832f66..9bd9e83e1e6b 100644 --- a/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp +++ b/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdMgrSetCmdDeleteCallback.cpp +// File: MICmdMgrSetCmdDeleteCallback.cpp // -// Overview: CSetClients implementation. +// Overview: CSetClients implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -26,85 +26,88 @@ namespace CMICmdMgrSetCmdDeleteCallback { //++ ------------------------------------------------------------------------------------ -// Details: CSetClients constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CSetClients constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CSetClients::CSetClients( void ) -: m_bClientUnregistered( false ) +CSetClients::CSetClients(void) + : m_bClientUnregistered(false) { } //++ ------------------------------------------------------------------------------------ -// Details: CSetClients destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CSetClients destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CSetClients::~CSetClients( void ) +CSetClients::~CSetClients(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Register an object to be called when a command object is deleted. -// Type: Method. -// Args: vObject - (R) A new interested client. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Register an object to be called when a command object is deleted. +// Type: Method. +// Args: vObject - (R) A new interested client. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CSetClients::Register( ICallback & vObject ) +bool +CSetClients::Register(ICallback &vObject) { - insert( &vObject ); + insert(&vObject); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Unregister an object from being called when a command object is deleted. -// Type: Method. -// Args: vObject - (R) The was interested client. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Unregister an object from being called when a command object is deleted. +// Type: Method. +// Args: vObject - (R) The was interested client. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CSetClients::Unregister( ICallback & vObject ) +bool +CSetClients::Unregister(ICallback &vObject) { - m_bClientUnregistered = true; - erase( &vObject ); + m_bClientUnregistered = true; + erase(&vObject); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Iterate all interested clients and tell them a command is being deleted. -// Type: Method. -// Args: vCmd - (RW) The command to be deleted. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Iterate all interested clients and tell them a command is being deleted. +// Type: Method. +// Args: vCmd - (RW) The command to be deleted. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -void CSetClients::Delete( SMICmdData & vCmd ) +void +CSetClients::Delete(SMICmdData &vCmd) { - m_bClientUnregistered = false; // Reset - iterator it = begin(); - while( it != end() ) - { - ICallback * pObj = *it; - pObj->Delete( vCmd ); + m_bClientUnregistered = false; // Reset + iterator it = begin(); + while (it != end()) + { + ICallback *pObj = *it; + pObj->Delete(vCmd); - if( m_bClientUnregistered ) - { - m_bClientUnregistered = false; // Reset - it = begin(); - } - else - // Next - ++it; - } + if (m_bClientUnregistered) + { + m_bClientUnregistered = false; // Reset + it = begin(); + } + else + // Next + ++it; + } } } // namespace CMICmdMgrSetCmdDeleteCallback diff --git a/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h b/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h index 3579d3582615..b969af0dacb9 100644 --- a/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h +++ b/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h @@ -8,16 +8,16 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmdMgrSetCmdDeleteCallback.h +// File: MICmdMgrSetCmdDeleteCallback.h // -// Overview: ICallback interface. -// CSetClients interface. +// Overview: ICallback interface. +// CSetClients interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -35,54 +35,52 @@ namespace CMICmdMgrSetCmdDeleteCallback { //++ ============================================================================ -// Details: MI Command Manager interface for client call back. -// Objects that want to be notified of a command being deleted -// inherit this interface and register interest in command object -// deletion. An object deleting a command must not do it itself but call -// the Command Manager CmdDelete() function to delete a command object. -// Gotchas: None. -// Authors: Illya Rudkin 21/02/2014. -// Changes: None. +// Details: MI Command Manager interface for client call back. +// Objects that want to be notified of a command being deleted +// inherit this interface and register interest in command object +// deletion. An object deleting a command must not do it itself but call +// the Command Manager CmdDelete() function to delete a command object. +// Gotchas: None. +// Authors: Illya Rudkin 21/02/2014. +// Changes: None. //-- class ICallback { -public: - virtual void Delete( SMICmdData & vCmd ) = 0; + public: + virtual void Delete(SMICmdData &vCmd) = 0; - /* dtor */ virtual ~ICallback( void ) {}; + /* dtor */ virtual ~ICallback(void){}; }; //++ ============================================================================ -// Details: MI Command Manager container for clients registered interest in command -// objects being deleted. Objects register an interest so when a command -// is to be deleted that object wanting the delete calls the Command -// Manager to delete the command object. In so do all other registered -// objects get called to about the deletion including the object wanting -// to do the delete in the first place. -// Gotchas: None. -// Authors: Illya Rudkin 21/02/2014. -// Changes: None. +// Details: MI Command Manager container for clients registered interest in command +// objects being deleted. Objects register an interest so when a command +// is to be deleted that object wanting the delete calls the Command +// Manager to delete the command object. In so do all other registered +// objects get called to about the deletion including the object wanting +// to do the delete in the first place. +// Gotchas: None. +// Authors: Illya Rudkin 21/02/2014. +// Changes: None. //-- -class CSetClients -: public std::set< class ICallback * > -, public CMICmnBase +class CSetClients : public std::set, public CMICmnBase { -// Methods: -public: - /* ctor */ CSetClients( void ); - - bool Register( class ICallback & vObject ); - bool Unregister( class ICallback & vObject ); - void Delete( SMICmdData & vCmdData ); + // Methods: + public: + /* ctor */ CSetClients(void); -// Overridden: -public: - // From CMICmnBase - /* dtor */ virtual ~CSetClients( void ); + bool Register(class ICallback &vObject); + bool Unregister(class ICallback &vObject); + void Delete(SMICmdData &vCmdData); -// Attributes: -private: - bool m_bClientUnregistered; // True = yes while deleting a client unregistered, false = no client unregistered during deletion + // Overridden: + public: + // From CMICmnBase + /* dtor */ virtual ~CSetClients(void); + + // Attributes: + private: + bool m_bClientUnregistered; // True = yes while deleting a client unregistered, false = no client unregistered during deletion }; } // namespace CMICmdMgrSetCmdDeleteCallback diff --git a/tools/lldb-mi/MICmnBase.cpp b/tools/lldb-mi/MICmnBase.cpp index 3da7a41b3336..fce6a1d25562 100644 --- a/tools/lldb-mi/MICmnBase.cpp +++ b/tools/lldb-mi/MICmnBase.cpp @@ -8,19 +8,19 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnBase.cpp +// File: MICmnBase.cpp // -// Overview: CMICmnBase implementation. +// Overview: CMICmnBase implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third party headers -#include // va_list, va_start, var_end +#include // va_list, va_start, var_end // In-house headers: #include "MICmnBase.h" @@ -28,117 +28,123 @@ #include "MICmnStreamStderr.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnBase constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnBase constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnBase::CMICmnBase( void ) -: m_strMILastErrorDescription( CMIUtilString() ) -, m_bInitialized( false ) -, m_pLog( &CMICmnLog::Instance() ) -, m_clientUsageRefCnt( 0 ) +CMICmnBase::CMICmnBase(void) + : m_strMILastErrorDescription(CMIUtilString()) + , m_bInitialized(false) + , m_pLog(&CMICmnLog::Instance()) + , m_clientUsageRefCnt(0) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnBase destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnBase destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnBase::~CMICmnBase( void ) +CMICmnBase::~CMICmnBase(void) { - m_pLog = NULL; + m_pLog = NULL; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve whether *this object has an error description set. -// Type: Method. -// Args: None. -// Return: bool - True = Yes already defined, false = empty discription. -// Throws: None. +// Details: Retrieve whether *this object has an error description set. +// Type: Method. +// Args: None. +// Return: bool - True = Yes already defined, false = empty discription. +// Throws: None. //-- -bool CMICmnBase::HaveErrorDescription( void ) const +bool +CMICmnBase::HaveErrorDescription(void) const { - return m_strMILastErrorDescription.empty(); + return m_strMILastErrorDescription.empty(); } - + //++ ------------------------------------------------------------------------------------ -// Details: Retrieve MI's last error condition. -// Type: Method. -// Args: None. -// Return: CMIUtilString & - Text description. -// Throws: None. +// Details: Retrieve MI's last error condition. +// Type: Method. +// Args: None. +// Return: CMIUtilString & - Text description. +// Throws: None. //-- -const CMIUtilString & CMICmnBase::GetErrorDescription( void ) const +const CMIUtilString & +CMICmnBase::GetErrorDescription(void) const { - return m_strMILastErrorDescription; + return m_strMILastErrorDescription; } - + //++ ------------------------------------------------------------------------------------ -// Details: Set MI's error condition description. This may be accessed by clients and -// seen by users. Message is available to the client using the server and sent -// to the Logger. -// Type: Method. -// Args: vrTxt - (R) Text description. -// Return: None. -// Throws: None. +// Details: Set MI's error condition description. This may be accessed by clients and +// seen by users. Message is available to the client using the server and sent +// to the Logger. +// Type: Method. +// Args: vrTxt - (R) Text description. +// Return: None. +// Throws: None. //-- -void CMICmnBase::SetErrorDescription( const CMIUtilString & vrTxt ) const +void +CMICmnBase::SetErrorDescription(const CMIUtilString &vrTxt) const { - m_strMILastErrorDescription = vrTxt; - if( !vrTxt.empty() ) - { - const CMIUtilString txt( CMIUtilString::Format( "Error: %s", vrTxt.c_str() ) ); - CMICmnStreamStderr::Instance().Write( txt ); - } + m_strMILastErrorDescription = vrTxt; + if (!vrTxt.empty()) + { + const CMIUtilString txt(CMIUtilString::Format("Error: %s", vrTxt.c_str())); + CMICmnStreamStderr::Instance().Write(txt); + } } //++ ------------------------------------------------------------------------------------ -// Details: Set MI's error condition description. This may be accessed by clients and -// seen by users. Message is available to the client using the server and sent -// to the Logger. -// Type: Method. -// Args: vrTxt - (R) Text description. -// Return: None. -// Throws: None. +// Details: Set MI's error condition description. This may be accessed by clients and +// seen by users. Message is available to the client using the server and sent +// to the Logger. +// Type: Method. +// Args: vrTxt - (R) Text description. +// Return: None. +// Throws: None. //-- -void CMICmnBase::SetErrorDescriptionNoLog( const CMIUtilString & vrTxt ) const +void +CMICmnBase::SetErrorDescriptionNoLog(const CMIUtilString &vrTxt) const { - m_strMILastErrorDescription = vrTxt; + m_strMILastErrorDescription = vrTxt; } - + //++ ------------------------------------------------------------------------------------ -// Details: Clear MI's error condition description. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: Clear MI's error condition description. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMICmnBase::ClrErrorDescription( void ) const +void +CMICmnBase::ClrErrorDescription(void) const { - m_strMILastErrorDescription.clear(); + m_strMILastErrorDescription.clear(); } //++ ------------------------------------------------------------------------------------ -// Details: Set MI's error condition description. This may be accessed by clients and -// seen by users. Message is available to the client using the server and sent -// to the Logger. -// Type: Method. -// Args: vrFormat - (R) Format string. -// ... - (R) Variable number of CMIUtilString type objects. -// Return: None. -// Throws: None. +// Details: Set MI's error condition description. This may be accessed by clients and +// seen by users. Message is available to the client using the server and sent +// to the Logger. +// Type: Method. +// Args: vFormat - (R) Format string. +// ... - (R) Variable number of CMIUtilString type objects. +// Return: None. +// Throws: None. //-- -void CMICmnBase::SetErrorDescriptionn( const CMIUtilString & vrFormat, ... ) const +void +CMICmnBase::SetErrorDescriptionn(const CMIUtilString vFormat, ...) const { - va_list args; - va_start( args, vrFormat ); - CMIUtilString strResult = CMIUtilString::FormatValist( vrFormat, args ); - va_end( args ); + va_list args; + va_start(args, vFormat); + CMIUtilString strResult = CMIUtilString::FormatValist(vFormat, args); + va_end(args); - SetErrorDescription( strResult ); -} \ No newline at end of file + SetErrorDescription(strResult); +} diff --git a/tools/lldb-mi/MICmnBase.h b/tools/lldb-mi/MICmnBase.h index db7338c5581f..01fdab4dd14f 100644 --- a/tools/lldb-mi/MICmnBase.h +++ b/tools/lldb-mi/MICmnBase.h @@ -8,53 +8,53 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnBase.h +// File: MICmnBase.h // -// Overview: CMICmnBase interface. +// Overview: CMICmnBase interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once // In-house headers: -#include "MIDataTypes.h" +#include "MIDataTypes.h" #include "MIUtilString.h" // Declarations: class CMICmnLog; //++ ============================================================================ -// Details: MI common code implementation base class. -// Gotchas: None. -// Authors: Illya Rudkin 28/01/2014. -// Changes: None. +// Details: MI common code implementation base class. +// Gotchas: None. +// Authors: Illya Rudkin 28/01/2014. +// Changes: None. //-- class CMICmnBase { -// Methods: -public: - /* ctor */ CMICmnBase( void ); - - bool HaveErrorDescription( void ) const; - const CMIUtilString & GetErrorDescription( void ) const; - void SetErrorDescription( const CMIUtilString & vrTxt ) const; - void SetErrorDescriptionn( const CMIUtilString & vrFormat, ... ) const; - void SetErrorDescriptionNoLog( const CMIUtilString & vrTxt ) const; - void ClrErrorDescription( void ) const; - -// Overrideable: -public: - /* dtor */ virtual ~CMICmnBase( void ); - -// Attributes: -protected: - mutable CMIUtilString m_strMILastErrorDescription; - bool m_bInitialized; // True = yes successfully initialized, false = no yet or failed - CMICmnLog * m_pLog; // Allow all derived classes to use the logger - MIint m_clientUsageRefCnt; // Count of client using *this object so not shutdown() object to early -}; \ No newline at end of file + // Methods: + public: + /* ctor */ CMICmnBase(void); + + bool HaveErrorDescription(void) const; + const CMIUtilString &GetErrorDescription(void) const; + void SetErrorDescription(const CMIUtilString &vrTxt) const; + void SetErrorDescriptionn(const CMIUtilString vFormat, ...) const; + void SetErrorDescriptionNoLog(const CMIUtilString &vrTxt) const; + void ClrErrorDescription(void) const; + + // Overrideable: + public: + /* dtor */ virtual ~CMICmnBase(void); + + // Attributes: + protected: + mutable CMIUtilString m_strMILastErrorDescription; + bool m_bInitialized; // True = yes successfully initialized, false = no yet or failed + CMICmnLog *m_pLog; // Allow all derived classes to use the logger + MIint m_clientUsageRefCnt; // Count of client using *this object so not shutdown() object to early +}; diff --git a/tools/lldb-mi/MICmnConfig.h b/tools/lldb-mi/MICmnConfig.h index 68093e87998b..830e2e3b562c 100644 --- a/tools/lldb-mi/MICmnConfig.h +++ b/tools/lldb-mi/MICmnConfig.h @@ -8,22 +8,22 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnConfig.h +// File: MICmnConfig.h // -// Overview: Common defines to guide feature inclusion at compile time. +// Overview: Common defines to guide feature inclusion at compile time. // // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once // 1 = Yes compile MI Driver version, 0 = compile original LLDB driver code only. // 0 was mainly just for testing purposes and so may be removed at a later time. -#define MICONFIG_COMPILE_MIDRIVER_VERSION 1 +#define MICONFIG_COMPILE_MIDRIVER_VERSION 1 // 1 = Show debug process attach modal dialog, 0 = do not show // For windows only ATM, other OS's code is an infinite loop which a debugger must change a value to continue @@ -47,4 +47,4 @@ #define MICONFIG_GIVE_WARNING_CMD_ARGS_NOT_HANDLED 1 // 1 = Enable MI Driver in MI mode to create a local debug session, 0 = Report "Not implemented" -#define MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION 0 \ No newline at end of file +#define MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION 0 diff --git a/tools/lldb-mi/MICmnLLDBBroadcaster.cpp b/tools/lldb-mi/MICmnLLDBBroadcaster.cpp index 743100ae7b0f..2b563c64d65a 100644 --- a/tools/lldb-mi/MICmnLLDBBroadcaster.cpp +++ b/tools/lldb-mi/MICmnLLDBBroadcaster.cpp @@ -8,82 +8,83 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLLDBBroadcaster.cpp +// File: MICmnLLDBBroadcaster.cpp // -// Overview: CMICmnLLDBBroadcaster implementation. +// Overview: CMICmnLLDBBroadcaster implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: #include "MICmnLLDBBroadcaster.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBBroadcaster constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnLLDBBroadcaster constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnLLDBBroadcaster::CMICmnLLDBBroadcaster( void ) -: lldb::SBBroadcaster( "MI driver" ) +CMICmnLLDBBroadcaster::CMICmnLLDBBroadcaster(void) + : lldb::SBBroadcaster("MI driver") { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBBroadcaster destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnLLDBBroadcaster destructor. +// Type: Overridable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnLLDBBroadcaster::~CMICmnLLDBBroadcaster( void ) +CMICmnLLDBBroadcaster::~CMICmnLLDBBroadcaster(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this broardcaster object. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Initialize resources for *this broardcaster object. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBBroadcaster::Initialize( void ) +bool +CMICmnLLDBBroadcaster::Initialize(void) { - m_clientUsageRefCnt++; + m_clientUsageRefCnt++; - if( m_bInitialized ) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - m_bInitialized = MIstatus::success; - - return m_bInitialized; + m_bInitialized = MIstatus::success; + + return m_bInitialized; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this broardcaster object. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Release resources for *this broardcaster object. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBBroadcaster::Shutdown( void ) +bool +CMICmnLLDBBroadcaster::Shutdown(void) { - if( --m_clientUsageRefCnt > 0 ) - return MIstatus::success; - - if( !m_bInitialized ) - return MIstatus::success; + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - m_bInitialized = false; + if (!m_bInitialized) + return MIstatus::success; - return MIstatus::success; -} + m_bInitialized = false; + return MIstatus::success; +} diff --git a/tools/lldb-mi/MICmnLLDBBroadcaster.h b/tools/lldb-mi/MICmnLLDBBroadcaster.h index 6c3300aefcc4..70d092589412 100644 --- a/tools/lldb-mi/MICmnLLDBBroadcaster.h +++ b/tools/lldb-mi/MICmnLLDBBroadcaster.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLLDBBroadcaster.h +// File: MICmnLLDBBroadcaster.h // -// Overview: CMICmnLLDBBroadcaster interface. +// Overview: CMICmnLLDBBroadcaster interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -27,35 +27,32 @@ #include "MIUtilSingletonBase.h" //++ ============================================================================ -// Details: MI derived class from LLDB SBBroardcaster API. +// Details: MI derived class from LLDB SBBroardcaster API. // -// *** This class (files) is a place holder until we know we need it or -// *** not +// *** This class (files) is a place holder until we know we need it or +// *** not // -// A singleton class. -// Gotchas: None. -// Authors: Illya Rudkin 28/02/2014. -// Changes: None. +// A singleton class. +// Gotchas: None. +// Authors: Illya Rudkin 28/02/2014. +// Changes: None. //-- -class CMICmnLLDBBroadcaster -: public CMICmnBase -, public lldb::SBBroadcaster -, public MI::ISingleton< CMICmnLLDBBroadcaster > +class CMICmnLLDBBroadcaster : public CMICmnBase, public lldb::SBBroadcaster, public MI::ISingleton { - friend MI::ISingleton< CMICmnLLDBBroadcaster >; + friend MI::ISingleton; -// Methods: -public: - bool Initialize( void ); - bool Shutdown( void ); -// Methods: -private: - /* ctor */ CMICmnLLDBBroadcaster( void ); - /* ctor */ CMICmnLLDBBroadcaster( const CMICmnLLDBBroadcaster & ); - void operator=( const CMICmnLLDBBroadcaster & ); + // Methods: + public: + bool Initialize(void); + bool Shutdown(void); + // Methods: + private: + /* ctor */ CMICmnLLDBBroadcaster(void); + /* ctor */ CMICmnLLDBBroadcaster(const CMICmnLLDBBroadcaster &); + void operator=(const CMICmnLLDBBroadcaster &); -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMICmnLLDBBroadcaster( void ); + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMICmnLLDBBroadcaster(void); }; diff --git a/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp b/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp index 3b7789ee1d63..3e9ed226182f 100644 --- a/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp +++ b/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp @@ -8,24 +8,24 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLLDBDebugSessionInfo.cpp +// File: MICmnLLDBDebugSessionInfo.cpp // -// Overview: CMICmnLLDBDebugSessionInfo implementation. +// Overview: CMICmnLLDBDebugSessionInfo implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third party headers: #include #ifdef _WIN32 - #include // For the ::_access() +#include // For the ::_access() #else - #include // For the ::access() -#endif // _WIN32 +#include // For the ::access() +#endif // _WIN32 #include // In-house headers: @@ -40,1273 +40,1319 @@ #include "MICmnLLDBUtilSBValue.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBDebugSessionInfo constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnLLDBDebugSessionInfo constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnLLDBDebugSessionInfo::CMICmnLLDBDebugSessionInfo( void ) -: m_rLldbDebugger( CMICmnLLDBDebugger::Instance().GetTheDebugger() ) -, m_rLlldbListener( CMICmnLLDBDebugger::Instance().GetTheListener() ) -, m_nBrkPointCntMax( INT32_MAX ) -, m_currentSelectedThread( LLDB_INVALID_THREAD_ID ) -, m_constStrSharedDataKeyWkDir( "Working Directory" ) -, m_constStrSharedDataSolibPath( "Solib Path" ) +CMICmnLLDBDebugSessionInfo::CMICmnLLDBDebugSessionInfo(void) + : m_rLldbDebugger(CMICmnLLDBDebugger::Instance().GetTheDebugger()) + , m_rLlldbListener(CMICmnLLDBDebugger::Instance().GetTheListener()) + , m_nBrkPointCntMax(INT32_MAX) + , m_currentSelectedThread(LLDB_INVALID_THREAD_ID) + , m_constStrSharedDataKeyWkDir("Working Directory") + , m_constStrSharedDataSolibPath("Solib Path") { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBDebugSessionInfo destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnLLDBDebugSessionInfo destructor. +// Type: Overridable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnLLDBDebugSessionInfo::~CMICmnLLDBDebugSessionInfo( void ) +CMICmnLLDBDebugSessionInfo::~CMICmnLLDBDebugSessionInfo(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this object. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Initialize resources for *this object. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::Initialize( void ) +bool +CMICmnLLDBDebugSessionInfo::Initialize(void) { - m_clientUsageRefCnt++; + m_clientUsageRefCnt++; + + if (m_bInitialized) + return MIstatus::success; - if( m_bInitialized ) - return MIstatus::success; + m_currentSelectedThread = LLDB_INVALID_THREAD_ID; + CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero(); - m_currentSelectedThread = LLDB_INVALID_THREAD_ID; - CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero(); + m_bInitialized = MIstatus::success; - m_bInitialized = MIstatus::success; - - return m_bInitialized; + return m_bInitialized; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this object. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Release resources for *this object. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::Shutdown( void ) +bool +CMICmnLLDBDebugSessionInfo::Shutdown(void) { - if( --m_clientUsageRefCnt > 0 ) - return MIstatus::success; - - if( !m_bInitialized ) - return MIstatus::success; - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Tidy up - bOk = SharedDataDestroy(); - if( !bOk ) - { - errMsg = CMIUtilString::Format( MIRSRC( IDS_DBGSESSION_ERR_SHARED_DATA_RELEASE ) ); - errMsg += "\n"; - } - m_vecActiveThreadId.clear(); - CMICmnLLDBDebugSessionInfoVarObj::VarObjClear(); - - m_bInitialized = false; - - return MIstatus::success; -} + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; + + if (!m_bInitialized) + return MIstatus::success; + + bool bOk = MIstatus::success; + CMIUtilString errMsg; + + // Tidy up + bOk = SharedDataDestroy(); + if (!bOk) + { + errMsg = CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_RELEASE)); + errMsg += "\n"; + } + m_vecActiveThreadId.clear(); + CMICmnLLDBDebugSessionInfoVarObj::VarObjClear(); + + m_bInitialized = false; + + return MIstatus::success; +} //++ ------------------------------------------------------------------------------------ -// Details: Command instances can create and share data between other instances of commands. -// Data can also be assigned by a command and retrieved by LLDB event handler. -// This function takes down those resources build up over the use of the commands. -// This function should be called when the creation and running of command has -// stopped i.e. application shutdown. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Command instances can create and share data between other instances of commands. +// Data can also be assigned by a command and retrieved by LLDB event handler. +// This function takes down those resources build up over the use of the commands. +// This function should be called when the creation and running of command has +// stopped i.e. application shutdown. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::SharedDataDestroy( void ) +bool +CMICmnLLDBDebugSessionInfo::SharedDataDestroy(void) { - m_mapIdToSessionData.Clear(); - m_vecVarObj.clear(); - m_mapBrkPtIdToBrkPtInfo.clear(); + m_mapIdToSessionData.Clear(); + m_vecVarObj.clear(); + m_mapBrkPtIdToBrkPtInfo.clear(); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Record information about a LLDB break point so that is can be recalled in other -// commands or LLDB event handling functions. -// Type: Method. -// Args: vBrkPtId - (R) LLDB break point ID. -// vrBrkPtInfo - (R) Break point information object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Record information about a LLDB break point so that is can be recalled in other +// commands or LLDB event handling functions. +// Type: Method. +// Args: vBrkPtId - (R) LLDB break point ID. +// vrBrkPtInfo - (R) Break point information object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfo( const MIuint vnBrkPtId, const SBrkPtInfo & vrBrkPtInfo ) +bool +CMICmnLLDBDebugSessionInfo::RecordBrkPtInfo(const MIuint vnBrkPtId, const SBrkPtInfo &vrBrkPtInfo) { - MapPairBrkPtIdToBrkPtInfo_t pr( vnBrkPtId, vrBrkPtInfo ); - m_mapBrkPtIdToBrkPtInfo.insert( pr ); + MapPairBrkPtIdToBrkPtInfo_t pr(vnBrkPtId, vrBrkPtInfo); + m_mapBrkPtIdToBrkPtInfo.insert(pr); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve information about a LLDB break point previous recorded either by -// commands or LLDB event handling functions. -// Type: Method. -// Args: vBrkPtId - (R) LLDB break point ID. -// vrwBrkPtInfo - (W) Break point information object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieve information about a LLDB break point previous recorded either by +// commands or LLDB event handling functions. +// Type: Method. +// Args: vBrkPtId - (R) LLDB break point ID. +// vrwBrkPtInfo - (W) Break point information object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoGet( const MIuint vnBrkPtId, SBrkPtInfo & vrwBrkPtInfo ) const +bool +CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoGet(const MIuint vnBrkPtId, SBrkPtInfo &vrwBrkPtInfo) const { - const MapBrkPtIdToBrkPtInfo_t::const_iterator it = m_mapBrkPtIdToBrkPtInfo.find( vnBrkPtId ); - if( it != m_mapBrkPtIdToBrkPtInfo.end() ) - { - vrwBrkPtInfo = (*it).second; - return MIstatus::success; - } - - return MIstatus::failure; + const MapBrkPtIdToBrkPtInfo_t::const_iterator it = m_mapBrkPtIdToBrkPtInfo.find(vnBrkPtId); + if (it != m_mapBrkPtIdToBrkPtInfo.end()) + { + vrwBrkPtInfo = (*it).second; + return MIstatus::success; + } + + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Delete information about a specific LLDB break point object. This function -// should be called when a LLDB break point is deleted. -// Type: Method. -// Args: vBrkPtId - (R) LLDB break point ID. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Delete information about a specific LLDB break point object. This function +// should be called when a LLDB break point is deleted. +// Type: Method. +// Args: vBrkPtId - (R) LLDB break point ID. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoDelete( const MIuint vnBrkPtId ) +bool +CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoDelete(const MIuint vnBrkPtId) { - const MapBrkPtIdToBrkPtInfo_t::const_iterator it = m_mapBrkPtIdToBrkPtInfo.find( vnBrkPtId ); - if( it != m_mapBrkPtIdToBrkPtInfo.end() ) - { - m_mapBrkPtIdToBrkPtInfo.erase( it ); - return MIstatus::success; - } - - return MIstatus::failure; + const MapBrkPtIdToBrkPtInfo_t::const_iterator it = m_mapBrkPtIdToBrkPtInfo.find(vnBrkPtId); + if (it != m_mapBrkPtIdToBrkPtInfo.end()) + { + m_mapBrkPtIdToBrkPtInfo.erase(it); + return MIstatus::success; + } + + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the specified thread's frame information. -// Type: Method. -// Args: vCmdData - (R) A command's information. -// vThreadIdx - (R) Thread index. -// vwrThreadFrames - (W) Frame data. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieve the specified thread's frame information. +// Type: Method. +// Args: vCmdData - (R) A command's information. +// vThreadIdx - (R) Thread index. +// vwrThreadFrames - (W) Frame data. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::GetThreadFrames( const SMICmdData & vCmdData, const MIuint vThreadIdx, CMIUtilString & vwrThreadFrames ) +bool +CMICmnLLDBDebugSessionInfo::GetThreadFrames(const SMICmdData &vCmdData, const MIuint vThreadIdx, CMIUtilString &vwrThreadFrames) { - lldb::SBThread thread = m_lldbProcess.GetThreadByIndexID( vThreadIdx ); - const uint32_t nFrames = thread.GetNumFrames(); - if( nFrames == 0 ) - { - // MI print "frame={}" - CMICmnMIValueTuple miValueTuple; - CMICmnMIValueResult miValueResult( "frame", miValueTuple ); - vwrThreadFrames = miValueResult.GetString(); - return MIstatus::success; - } - - // MI print "frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"}, ..." - CMIUtilString strListCommaSeperated; - for( MIuint nLevel = 0; nLevel < nFrames; nLevel++ ) - { - lldb::SBFrame frame = thread.GetFrameAtIndex( nLevel ); - lldb::addr_t pc = 0; - CMIUtilString fnName; - CMIUtilString fileName; - CMIUtilString path; - MIuint nLine = 0; - if( !GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) ) - return MIstatus::failure; - - // Function args - CMICmnMIValueList miValueList( true ); - const MIuint maskVarTypes = 0x1000; - if( !MIResponseFormVariableInfo( frame, maskVarTypes, miValueList ) ) - return MIstatus::failure; - - const MIchar * pUnknown = "??"; - if( fnName != pUnknown ) - { - std::replace( fnName.begin(), fnName.end(), ')', ' ' ); - std::replace( fnName.begin(), fnName.end(), '(', ' ' ); - std::replace( fnName.begin(), fnName.end(), '\'', ' ' ); - } - - CMICmnMIValueTuple miValueTuple; - const CMIUtilString strLevel( CMIUtilString::Format( "%d", nLevel ) ); - const CMICmnMIValueConst miValueConst( strLevel ); - const CMICmnMIValueResult miValueResult( "level", miValueConst ); - miValueTuple.Add( miValueResult ); - if( !MIResponseFormFrameInfo2( pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple ) ) - return MIstatus::failure; - - const CMICmnMIValueResult miValueResult2( "frame", miValueTuple ); - if( nLevel != 0 ) - strListCommaSeperated += ","; - strListCommaSeperated += miValueResult2.GetString(); - } - - vwrThreadFrames = strListCommaSeperated; - - return MIstatus::success; + lldb::SBThread thread = m_lldbProcess.GetThreadByIndexID(vThreadIdx); + const uint32_t nFrames = thread.GetNumFrames(); + if (nFrames == 0) + { + // MI print "frame={}" + CMICmnMIValueTuple miValueTuple; + CMICmnMIValueResult miValueResult("frame", miValueTuple); + vwrThreadFrames = miValueResult.GetString(); + return MIstatus::success; + } + + // MI print + // "frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"}, + // ..." + CMIUtilString strListCommaSeperated; + for (MIuint nLevel = 0; nLevel < nFrames; nLevel++) + { + lldb::SBFrame frame = thread.GetFrameAtIndex(nLevel); + lldb::addr_t pc = 0; + CMIUtilString fnName; + CMIUtilString fileName; + CMIUtilString path; + MIuint nLine = 0; + if (!GetFrameInfo(frame, pc, fnName, fileName, path, nLine)) + return MIstatus::failure; + + // Function args + CMICmnMIValueList miValueList(true); + const MIuint maskVarTypes = eVariableType_Arguments; + if (!MIResponseFormVariableInfo(frame, maskVarTypes, miValueList)) + return MIstatus::failure; + + const MIchar *pUnknown = "??"; + if (fnName != pUnknown) + { + std::replace(fnName.begin(), fnName.end(), ')', ' '); + std::replace(fnName.begin(), fnName.end(), '(', ' '); + std::replace(fnName.begin(), fnName.end(), '\'', ' '); + } + + CMICmnMIValueTuple miValueTuple; + const CMIUtilString strLevel(CMIUtilString::Format("%d", nLevel)); + const CMICmnMIValueConst miValueConst(strLevel); + const CMICmnMIValueResult miValueResult("level", miValueConst); + miValueTuple.Add(miValueResult); + if (!MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple)) + return MIstatus::failure; + + const CMICmnMIValueResult miValueResult2("frame", miValueTuple); + if (nLevel != 0) + strListCommaSeperated += ","; + strListCommaSeperated += miValueResult2.GetString(); + } + + vwrThreadFrames = strListCommaSeperated; + + return MIstatus::success; } // Todo: Refactor maybe to so only one function with this name, but not just yet //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the specified thread's frame information. -// Type: Method. -// Args: vCmdData - (R) A command's information. -// vThreadIdx - (R) Thread index. -// vwrThreadFrames - (W) Frame data. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieve the specified thread's frame information. +// Type: Method. +// Args: vCmdData - (R) A command's information. +// vThreadIdx - (R) Thread index. +// vwrThreadFrames - (W) Frame data. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::GetThreadFrames2( const SMICmdData & vCmdData, const MIuint vThreadIdx, CMIUtilString & vwrThreadFrames ) +bool +CMICmnLLDBDebugSessionInfo::GetThreadFrames2(const SMICmdData &vCmdData, const MIuint vThreadIdx, CMIUtilString &vwrThreadFrames) { - lldb::SBThread thread = m_lldbProcess.GetThreadByIndexID( vThreadIdx ); - const uint32_t nFrames = thread.GetNumFrames(); - if( nFrames == 0 ) - { - // MI print "frame={}" - CMICmnMIValueTuple miValueTuple; - CMICmnMIValueResult miValueResult( "frame", miValueTuple ); - vwrThreadFrames = miValueResult.GetString(); - return MIstatus::success; - } - - // MI print "frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"}, ..." - CMIUtilString strListCommaSeperated; - for( MIuint nLevel = 0; nLevel < nFrames; nLevel++ ) - { - lldb::SBFrame frame = thread.GetFrameAtIndex( nLevel ); - lldb::addr_t pc = 0; - CMIUtilString fnName; - CMIUtilString fileName; - CMIUtilString path; - MIuint nLine = 0; - if( !GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) ) - return MIstatus::failure; - - // Function args - CMICmnMIValueList miValueList( true ); - const MIuint maskVarTypes = 0x1000; - if( !MIResponseFormVariableInfo2( frame, maskVarTypes, miValueList ) ) - return MIstatus::failure; - - const MIchar * pUnknown = "??"; - if( fnName != pUnknown ) - { - std::replace( fnName.begin(), fnName.end(), ')', ' ' ); - std::replace( fnName.begin(), fnName.end(), '(', ' ' ); - std::replace( fnName.begin(), fnName.end(), '\'', ' ' ); - } - - CMICmnMIValueTuple miValueTuple; - const CMIUtilString strLevel( CMIUtilString::Format( "%d", nLevel ) ); - const CMICmnMIValueConst miValueConst( strLevel ); - const CMICmnMIValueResult miValueResult( "level", miValueConst ); - miValueTuple.Add( miValueResult ); - if( !MIResponseFormFrameInfo2( pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple ) ) - return MIstatus::failure; - - const CMICmnMIValueResult miValueResult2( "frame", miValueTuple ); - if( nLevel != 0 ) - strListCommaSeperated += ","; - strListCommaSeperated += miValueResult2.GetString(); - } - - vwrThreadFrames = strListCommaSeperated; - - return MIstatus::success; + lldb::SBThread thread = m_lldbProcess.GetThreadByIndexID(vThreadIdx); + const uint32_t nFrames = thread.GetNumFrames(); + if (nFrames == 0) + { + // MI print "frame={}" + CMICmnMIValueTuple miValueTuple; + CMICmnMIValueResult miValueResult("frame", miValueTuple); + vwrThreadFrames = miValueResult.GetString(); + return MIstatus::success; + } + + // MI print + // "frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"}, + // ..." + CMIUtilString strListCommaSeperated; + for (MIuint nLevel = 0; nLevel < nFrames; nLevel++) + { + lldb::SBFrame frame = thread.GetFrameAtIndex(nLevel); + lldb::addr_t pc = 0; + CMIUtilString fnName; + CMIUtilString fileName; + CMIUtilString path; + MIuint nLine = 0; + if (!GetFrameInfo(frame, pc, fnName, fileName, path, nLine)) + return MIstatus::failure; + + // Function args + CMICmnMIValueList miValueList(true); + const MIuint maskVarTypes = eVariableType_Arguments; + if (!MIResponseFormVariableInfo2(frame, maskVarTypes, miValueList)) + return MIstatus::failure; + + const MIchar *pUnknown = "??"; + if (fnName != pUnknown) + { + std::replace(fnName.begin(), fnName.end(), ')', ' '); + std::replace(fnName.begin(), fnName.end(), '(', ' '); + std::replace(fnName.begin(), fnName.end(), '\'', ' '); + } + + CMICmnMIValueTuple miValueTuple; + const CMIUtilString strLevel(CMIUtilString::Format("%d", nLevel)); + const CMICmnMIValueConst miValueConst(strLevel); + const CMICmnMIValueResult miValueResult("level", miValueConst); + miValueTuple.Add(miValueResult); + if (!MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple)) + return MIstatus::failure; + + const CMICmnMIValueResult miValueResult2("frame", miValueTuple); + if (nLevel != 0) + strListCommaSeperated += ","; + strListCommaSeperated += miValueResult2.GetString(); + } + + vwrThreadFrames = strListCommaSeperated; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Return the resolved file's path for the given file. -// Type: Method. -// Args: vCmdData - (R) A command's information. -// vPath - (R) Original path. -// vwrResolvedPath - (W) Resolved path. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Return the resolved file's path for the given file. +// Type: Method. +// Args: vCmdData - (R) A command's information. +// vPath - (R) Original path. +// vwrResolvedPath - (W) Resolved path. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::ResolvePath( const SMICmdData & vCmdData, const CMIUtilString & vPath, CMIUtilString & vwrResolvedPath ) +bool +CMICmnLLDBDebugSessionInfo::ResolvePath(const SMICmdData &vCmdData, const CMIUtilString &vPath, CMIUtilString &vwrResolvedPath) { - // ToDo: Verify this code as it does not work as vPath is always empty + // ToDo: Verify this code as it does not work as vPath is always empty - CMIUtilString strResolvedPath; - if( !SharedDataRetrieve< CMIUtilString >( m_constStrSharedDataKeyWkDir, strResolvedPath ) ) - { - vwrResolvedPath = ""; - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_SHARED_DATA_NOT_FOUND ), vCmdData.strMiCmd.c_str(), m_constStrSharedDataKeyWkDir.c_str() ) ); - return MIstatus::failure; - } + CMIUtilString strResolvedPath; + if (!SharedDataRetrieve(m_constStrSharedDataKeyWkDir, strResolvedPath)) + { + vwrResolvedPath = ""; + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SHARED_DATA_NOT_FOUND), vCmdData.strMiCmd.c_str(), + m_constStrSharedDataKeyWkDir.c_str())); + return MIstatus::failure; + } - vwrResolvedPath = vPath; + vwrResolvedPath = vPath; - return ResolvePath( strResolvedPath, vwrResolvedPath ); + return ResolvePath(strResolvedPath, vwrResolvedPath); } //++ ------------------------------------------------------------------------------------ -// Details: Return the resolved file's path for the given file. -// Type: Method. -// Args: vstrUnknown - (R) String assigned to path when resolved path is empty. -// vwrResolvedPath - (RW) The original path overwritten with resolved path. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Return the resolved file's path for the given file. +// Type: Method. +// Args: vstrUnknown - (R) String assigned to path when resolved path is empty. +// vwrResolvedPath - (RW) The original path overwritten with resolved path. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::ResolvePath( const CMIUtilString & vstrUnknown, CMIUtilString & vwrResolvedPath ) +bool +CMICmnLLDBDebugSessionInfo::ResolvePath(const CMIUtilString &vstrUnknown, CMIUtilString &vwrResolvedPath) { - if( vwrResolvedPath.size() < 1 ) - { - vwrResolvedPath = vstrUnknown; - return MIstatus::success; - } - - bool bOk = MIstatus::success; - - CMIUtilString::VecString_t vecPathFolders; - const MIuint nSplits = vwrResolvedPath.Split( "/", vecPathFolders ); MIunused( nSplits ); - MIuint nFoldersBack = 1; // 1 is just the file (last element of vector) - while( bOk && (vecPathFolders.size() >= nFoldersBack) ) - { - CMIUtilString strTestPath; - MIuint nFoldersToAdd = nFoldersBack; - while( nFoldersToAdd > 0 ) - { - strTestPath += "/"; - strTestPath += vecPathFolders[ vecPathFolders.size() - nFoldersToAdd ]; - nFoldersToAdd--; - } - bool bYesAccessible = false; - bOk = AccessPath( strTestPath, bYesAccessible ); - if( bYesAccessible ) - { - vwrResolvedPath = strTestPath; - return MIstatus::success; - } - else - nFoldersBack++; - } - - // No files exist in the union of working directory and debuginfo path + if (vwrResolvedPath.size() < 1) + { + vwrResolvedPath = vstrUnknown; + return MIstatus::success; + } + + bool bOk = MIstatus::success; + + CMIUtilString::VecString_t vecPathFolders; + const MIuint nSplits = vwrResolvedPath.Split("/", vecPathFolders); + MIunused(nSplits); + MIuint nFoldersBack = 1; // 1 is just the file (last element of vector) + while (bOk && (vecPathFolders.size() >= nFoldersBack)) + { + CMIUtilString strTestPath; + MIuint nFoldersToAdd = nFoldersBack; + while (nFoldersToAdd > 0) + { + strTestPath += "/"; + strTestPath += vecPathFolders[vecPathFolders.size() - nFoldersToAdd]; + nFoldersToAdd--; + } + bool bYesAccessible = false; + bOk = AccessPath(strTestPath, bYesAccessible); + if (bYesAccessible) + { + vwrResolvedPath = strTestPath; + return MIstatus::success; + } + else + nFoldersBack++; + } + + // No files exist in the union of working directory and debuginfo path // Simply use the debuginfo path and let the IDE handle it. - - return bOk; + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Determine the given file path exists or not. -// Type: Method. -// Args: vPath - (R) File name path. -// vwbYesAccessible - (W) True - file exists, false = does not exist. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Determine the given file path exists or not. +// Type: Method. +// Args: vPath - (R) File name path. +// vwbYesAccessible - (W) True - file exists, false = does not exist. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::AccessPath( const CMIUtilString & vPath, bool & vwbYesAccessible ) +bool +CMICmnLLDBDebugSessionInfo::AccessPath(const CMIUtilString &vPath, bool &vwbYesAccessible) { #ifdef _WIN32 - vwbYesAccessible = (::_access( vPath.c_str(), 0 ) == 0); + vwbYesAccessible = (::_access(vPath.c_str(), 0) == 0); #else - vwbYesAccessible = (::access( vPath.c_str(), 0 ) == 0); + vwbYesAccessible = (::access(vPath.c_str(), 0) == 0); #endif // _WIN32 - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the -// tuple type object past in. -// Type: Method. -// Args: vCmdData - (R) A command's information. -// vrThread - (R) LLDB thread object. -// vwrMIValueTuple - (W) MI value tuple object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Form MI partial response by appending more MI value type objects to the +// tuple type object past in. +// Type: Method. +// Args: vCmdData - (R) A command's information. +// vrThread - (R) LLDB thread object. +// vwrMIValueTuple - (W) MI value tuple object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo( const SMICmdData & vCmdData, const lldb::SBThread & vrThread, CMICmnMIValueTuple & vwrMIValueTuple ) +bool +CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo(const SMICmdData &vCmdData, const lldb::SBThread &vrThread, + CMICmnMIValueTuple &vwrMIValueTuple) { - lldb::SBThread & rThread = const_cast< lldb::SBThread & >( vrThread ); - - CMIUtilString strFrames; - if( !GetThreadFrames( vCmdData, rThread.GetIndexID(), strFrames ) ) - return MIstatus::failure; - - const bool bSuspended = rThread.IsSuspended(); - const lldb::StopReason eReason = rThread.GetStopReason(); - const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid)); - const CMIUtilString strState( (bSuspended || bValidReason) ? "stopped" : "running" ); - - // Add "id" - const CMIUtilString strId( CMIUtilString::Format( "%d", rThread.GetIndexID() ) ); - const CMICmnMIValueConst miValueConst1( strId ); - const CMICmnMIValueResult miValueResult1( "id", miValueConst1 ); - if( !vwrMIValueTuple.Add( miValueResult1 ) ) - return MIstatus::failure; - - // Add "target-id" - const MIchar * pThreadName = rThread.GetName(); - const MIuint len = (pThreadName != nullptr) ? CMIUtilString( pThreadName ).length() : 0; - const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && CMIUtilString::IsAllValidAlphaAndNumeric( *pThreadName ) ); // 32 is arbitary number - const MIchar * pThrdFmt = bHaveName ? "%s" : "Thread %d"; - CMIUtilString strThread; - if( bHaveName ) - strThread = CMIUtilString::Format( pThrdFmt, pThreadName ); - else - strThread = CMIUtilString::Format( pThrdFmt, rThread.GetIndexID() ); - const CMICmnMIValueConst miValueConst2( strThread ); - const CMICmnMIValueResult miValueResult2( "target-id", miValueConst2 ); - if( !vwrMIValueTuple.Add( miValueResult2 ) ) - return MIstatus::failure; - - // Add "frame" - const CMICmnMIValueConst miValueConst3( strFrames, true ); - if( !vwrMIValueTuple.Add( miValueConst3, false ) ) - return MIstatus::failure; - - // Add "state" - const CMICmnMIValueConst miValueConst4( strState ); - const CMICmnMIValueResult miValueResult4( "state", miValueConst4 ); - if( !vwrMIValueTuple.Add( miValueResult4 ) ) - return MIstatus::failure; - - return MIstatus::success; + lldb::SBThread &rThread = const_cast(vrThread); + + CMIUtilString strFrames; + if (!GetThreadFrames(vCmdData, rThread.GetIndexID(), strFrames)) + return MIstatus::failure; + + const bool bSuspended = rThread.IsSuspended(); + const lldb::StopReason eReason = rThread.GetStopReason(); + const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid)); + const CMIUtilString strState((bSuspended || bValidReason) ? "stopped" : "running"); + + // Add "id" + const CMIUtilString strId(CMIUtilString::Format("%d", rThread.GetIndexID())); + const CMICmnMIValueConst miValueConst1(strId); + const CMICmnMIValueResult miValueResult1("id", miValueConst1); + if (!vwrMIValueTuple.Add(miValueResult1)) + return MIstatus::failure; + + // Add "target-id" + const MIchar *pThreadName = rThread.GetName(); + const MIuint len = (pThreadName != nullptr) ? CMIUtilString(pThreadName).length() : 0; + const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && + CMIUtilString::IsAllValidAlphaAndNumeric(*pThreadName)); // 32 is arbitary number + const MIchar *pThrdFmt = bHaveName ? "%s" : "Thread %d"; + CMIUtilString strThread; + if (bHaveName) + strThread = CMIUtilString::Format(pThrdFmt, pThreadName); + else + strThread = CMIUtilString::Format(pThrdFmt, rThread.GetIndexID()); + const CMICmnMIValueConst miValueConst2(strThread); + const CMICmnMIValueResult miValueResult2("target-id", miValueConst2); + if (!vwrMIValueTuple.Add(miValueResult2)) + return MIstatus::failure; + + // Add "frame" + const CMICmnMIValueConst miValueConst3(strFrames, true); + if (!vwrMIValueTuple.Add(miValueConst3, false)) + return MIstatus::failure; + + // Add "state" + const CMICmnMIValueConst miValueConst4(strState); + const CMICmnMIValueResult miValueResult4("state", miValueConst4); + if (!vwrMIValueTuple.Add(miValueResult4)) + return MIstatus::failure; + + return MIstatus::success; } // Todo: Refactor maybe to so only one function with this name, but not just yet //++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the -// tuple type object past in. -// Type: Method. -// Args: vCmdData - (R) A command's information. -// vrThread - (R) LLDB thread object. -// vwrMIValueTuple - (W) MI value tuple object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Form MI partial response by appending more MI value type objects to the +// tuple type object past in. +// Type: Method. +// Args: vCmdData - (R) A command's information. +// vrThread - (R) LLDB thread object. +// vwrMIValueTuple - (W) MI value tuple object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo3( const SMICmdData & vCmdData, const lldb::SBThread & vrThread, CMICmnMIValueTuple & vwrMIValueTuple ) +bool +CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo3(const SMICmdData &vCmdData, const lldb::SBThread &vrThread, + CMICmnMIValueTuple &vwrMIValueTuple) { - lldb::SBThread & rThread = const_cast< lldb::SBThread & >( vrThread ); - - CMIUtilString strFrames; - if( !GetThreadFrames2( vCmdData, rThread.GetIndexID(), strFrames ) ) - return MIstatus::failure; - - const bool bSuspended = rThread.IsSuspended(); - const lldb::StopReason eReason = rThread.GetStopReason(); - const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid)); - const CMIUtilString strState( (bSuspended || bValidReason) ? "stopped" : "running" ); - - // Add "id" - const CMIUtilString strId( CMIUtilString::Format( "%d", rThread.GetIndexID() ) ); - const CMICmnMIValueConst miValueConst1( strId ); - const CMICmnMIValueResult miValueResult1( "id", miValueConst1 ); - if( !vwrMIValueTuple.Add( miValueResult1 ) ) - return MIstatus::failure; - - // Add "target-id" - const MIchar * pThreadName = rThread.GetName(); - const MIuint len = (pThreadName != nullptr) ? CMIUtilString( pThreadName ).length() : 0; - const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && CMIUtilString::IsAllValidAlphaAndNumeric( *pThreadName ) ); // 32 is arbitary number - const MIchar * pThrdFmt = bHaveName ? "%s" : "Thread %d"; - CMIUtilString strThread; - if( bHaveName ) - strThread = CMIUtilString::Format( pThrdFmt, pThreadName ); - else - strThread = CMIUtilString::Format( pThrdFmt, rThread.GetIndexID() ); - const CMICmnMIValueConst miValueConst2( strThread ); - const CMICmnMIValueResult miValueResult2( "target-id", miValueConst2 ); - if( !vwrMIValueTuple.Add( miValueResult2 ) ) - return MIstatus::failure; - - // Add "frame" - const CMICmnMIValueConst miValueConst3( strFrames, true ); - if( !vwrMIValueTuple.Add( miValueConst3, false ) ) - return MIstatus::failure; - - // Add "state" - const CMICmnMIValueConst miValueConst4( strState ); - const CMICmnMIValueResult miValueResult4( "state", miValueConst4 ); - if( !vwrMIValueTuple.Add( miValueResult4 ) ) - return MIstatus::failure; - - return MIstatus::success; + lldb::SBThread &rThread = const_cast(vrThread); + + CMIUtilString strFrames; + if (!GetThreadFrames2(vCmdData, rThread.GetIndexID(), strFrames)) + return MIstatus::failure; + + const bool bSuspended = rThread.IsSuspended(); + const lldb::StopReason eReason = rThread.GetStopReason(); + const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid)); + const CMIUtilString strState((bSuspended || bValidReason) ? "stopped" : "running"); + + // Add "id" + const CMIUtilString strId(CMIUtilString::Format("%d", rThread.GetIndexID())); + const CMICmnMIValueConst miValueConst1(strId); + const CMICmnMIValueResult miValueResult1("id", miValueConst1); + if (!vwrMIValueTuple.Add(miValueResult1)) + return MIstatus::failure; + + // Add "target-id" + const MIchar *pThreadName = rThread.GetName(); + const MIuint len = (pThreadName != nullptr) ? CMIUtilString(pThreadName).length() : 0; + const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && + CMIUtilString::IsAllValidAlphaAndNumeric(*pThreadName)); // 32 is arbitary number + const MIchar *pThrdFmt = bHaveName ? "%s" : "Thread %d"; + CMIUtilString strThread; + if (bHaveName) + strThread = CMIUtilString::Format(pThrdFmt, pThreadName); + else + strThread = CMIUtilString::Format(pThrdFmt, rThread.GetIndexID()); + const CMICmnMIValueConst miValueConst2(strThread); + const CMICmnMIValueResult miValueResult2("target-id", miValueConst2); + if (!vwrMIValueTuple.Add(miValueResult2)) + return MIstatus::failure; + + // Add "frame" + const CMICmnMIValueConst miValueConst3(strFrames, true); + if (!vwrMIValueTuple.Add(miValueConst3, false)) + return MIstatus::failure; + + // Add "state" + const CMICmnMIValueConst miValueConst4(strState); + const CMICmnMIValueResult miValueResult4("state", miValueConst4); + if (!vwrMIValueTuple.Add(miValueResult4)) + return MIstatus::failure; + + return MIstatus::success; } // Todo: Refactor maybe to so only one function with this name, but not just yet //++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the -// tuple type object past in. -// Type: Method. -// Args: vCmdData - (R) A command's information. -// vrThread - (R) LLDB thread object. -// vwrMIValueTuple - (W) MI value tuple object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Form MI partial response by appending more MI value type objects to the +// tuple type object past in. +// Type: Method. +// Args: vCmdData - (R) A command's information. +// vrThread - (R) LLDB thread object. +// vwrMIValueTuple - (W) MI value tuple object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo2( const SMICmdData & vCmdData, const lldb::SBThread & vrThread, CMICmnMIValueTuple & vwrMIValueTuple ) +bool +CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo2(const SMICmdData &vCmdData, const lldb::SBThread &vrThread, + CMICmnMIValueTuple &vwrMIValueTuple) { - lldb::SBThread & rThread = const_cast< lldb::SBThread & >( vrThread ); - - const bool bSuspended = rThread.IsSuspended(); - const lldb::StopReason eReason = rThread.GetStopReason(); - const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid)); - const CMIUtilString strState( (bSuspended || bValidReason) ? "stopped" : "running" ); - - // Add "id" - const CMIUtilString strId( CMIUtilString::Format( "%d", rThread.GetIndexID() ) ); - const CMICmnMIValueConst miValueConst1( strId ); - const CMICmnMIValueResult miValueResult1( "id", miValueConst1 ); - if( !vwrMIValueTuple.Add( miValueResult1 ) ) - return MIstatus::failure; - - // Add "target-id" - const MIchar * pThreadName = rThread.GetName(); - const MIuint len = (pThreadName != nullptr) ? CMIUtilString( pThreadName ).length() : 0; - const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && CMIUtilString::IsAllValidAlphaAndNumeric( *pThreadName ) ); // 32 is arbitary number - const MIchar * pThrdFmt = bHaveName ? "%s" : "Thread %d"; - CMIUtilString strThread; - if( bHaveName ) - strThread = CMIUtilString::Format( pThrdFmt, pThreadName ); - else - strThread = CMIUtilString::Format( pThrdFmt, rThread.GetIndexID() ); - const CMICmnMIValueConst miValueConst2( strThread ); - const CMICmnMIValueResult miValueResult2( "target-id", miValueConst2 ); - if( !vwrMIValueTuple.Add( miValueResult2 ) ) - return MIstatus::failure; - - // Add "state" - const CMICmnMIValueConst miValueConst4( strState ); - const CMICmnMIValueResult miValueResult4( "state", miValueConst4 ); - if( !vwrMIValueTuple.Add( miValueResult4 ) ) - return MIstatus::failure; - - return MIstatus::success; + lldb::SBThread &rThread = const_cast(vrThread); + + const bool bSuspended = rThread.IsSuspended(); + const lldb::StopReason eReason = rThread.GetStopReason(); + const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid)); + const CMIUtilString strState((bSuspended || bValidReason) ? "stopped" : "running"); + + // Add "id" + const CMIUtilString strId(CMIUtilString::Format("%d", rThread.GetIndexID())); + const CMICmnMIValueConst miValueConst1(strId); + const CMICmnMIValueResult miValueResult1("id", miValueConst1); + if (!vwrMIValueTuple.Add(miValueResult1)) + return MIstatus::failure; + + // Add "target-id" + const MIchar *pThreadName = rThread.GetName(); + const MIuint len = (pThreadName != nullptr) ? CMIUtilString(pThreadName).length() : 0; + const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && + CMIUtilString::IsAllValidAlphaAndNumeric(*pThreadName)); // 32 is arbitary number + const MIchar *pThrdFmt = bHaveName ? "%s" : "Thread %d"; + CMIUtilString strThread; + if (bHaveName) + strThread = CMIUtilString::Format(pThrdFmt, pThreadName); + else + strThread = CMIUtilString::Format(pThrdFmt, rThread.GetIndexID()); + const CMICmnMIValueConst miValueConst2(strThread); + const CMICmnMIValueResult miValueResult2("target-id", miValueConst2); + if (!vwrMIValueTuple.Add(miValueResult2)) + return MIstatus::failure; + + // Add "state" + const CMICmnMIValueConst miValueConst4(strState); + const CMICmnMIValueResult miValueResult4("state", miValueConst4); + if (!vwrMIValueTuple.Add(miValueResult4)) + return MIstatus::failure; + + return MIstatus::success; } // Todo: Refactor maybe to so only one function with this name, but not just yet //++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the -// tuple type object past in. -// Type: Method. -// Args: vrFrame - (R) LLDB thread object. -// vMaskVarTypes - (R) 0x1000 = arguments, -// 0x0100 = locals, -// 0x0010 = statics, -// 0x0001 = in scope only. -// vwrMIValueList - (W) MI value list object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Form MI partial response by appending more MI value type objects to the +// tuple type object past in. +// Type: Method. +// Args: vrFrame - (R) LLDB thread object. +// vMaskVarTypes - (R) Construed according to VariableType_e. +// vwrMIValueList - (W) MI value list object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo2( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList ) +bool +CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo2(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes, + CMICmnMIValueList &vwrMiValueList) { - bool bOk = MIstatus::success; - lldb::SBFrame & rFrame = const_cast< lldb::SBFrame & >( vrFrame ); - - const bool bArg = (vMaskVarTypes & 0x1000); - const bool bLocals = (vMaskVarTypes & 0x0100); - const bool bStatics = (vMaskVarTypes & 0x0010); - const bool bInScopeOnly = (vMaskVarTypes & 0x0001); - lldb::SBValueList listArg = rFrame.GetVariables( bArg, bLocals, bStatics, bInScopeOnly ); - const MIuint nArgs = listArg.GetSize(); - for( MIuint i = 0; bOk && (i < nArgs); i++ ) - { - lldb::SBValue value = listArg.GetValueAtIndex( i ); - const CMICmnLLDBUtilSBValue utilValue( value ); - const CMICmnMIValueConst miValueConst( utilValue.GetName() ); - const CMICmnMIValueResult miValueResult( "name", miValueConst ); - CMICmnMIValueTuple miValueTuple( miValueResult ); - const CMICmnMIValueConst miValueConst2( utilValue.GetValue() ); - const CMICmnMIValueResult miValueResult2( "value", miValueConst2 ); - miValueTuple.Add( miValueResult2 ); - bOk = vwrMiValueList.Add( miValueTuple ); - } - - return bOk; + bool bOk = MIstatus::success; + lldb::SBFrame &rFrame = const_cast(vrFrame); + + const bool bArg = (vMaskVarTypes & eVariableType_Arguments); + const bool bLocals = (vMaskVarTypes & eVariableType_Locals); + const bool bStatics = (vMaskVarTypes & eVariableType_Statics); + const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope); + lldb::SBValueList listArg = rFrame.GetVariables(bArg, bLocals, bStatics, bInScopeOnly); + const MIuint nArgs = listArg.GetSize(); + for (MIuint i = 0; bOk && (i < nArgs); i++) + { + lldb::SBValue value = listArg.GetValueAtIndex(i); + const CMICmnLLDBUtilSBValue utilValue(value); + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueConst miValueConst2(utilValue.GetValue()); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + bOk = vwrMiValueList.Add(miValueTuple); + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the -// tuple type object past in. -// Type: Method. -// Args: vrFrame - (R) LLDB thread object. -// vMaskVarTypes - (R) 0x1000 = arguments, -// 0x0100 = locals, -// 0x0010 = statics, -// 0x0001 = in scope only. -// vwrMIValueList - (W) MI value list object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Form MI partial response by appending more MI value type objects to the +// tuple type object past in. +// Type: Method. +// Args: vrFrame - (R) LLDB thread object. +// vMaskVarTypes - (R) Construed according to VariableType_e. +// vwrMIValueList - (W) MI value list object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList ) +bool +CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes, + CMICmnMIValueList &vwrMiValueList) { - bool bOk = MIstatus::success; - lldb::SBFrame & rFrame = const_cast< lldb::SBFrame & >( vrFrame ); - - const bool bArg = (vMaskVarTypes & 0x1000); - const bool bLocals = (vMaskVarTypes & 0x0100); - const bool bStatics = (vMaskVarTypes & 0x0010); - const bool bInScopeOnly = (vMaskVarTypes & 0x0001); - const MIuint nMaxRecusiveDepth = 10; - MIuint nCurrentRecursiveDepth = 0; - lldb::SBValueList listArg = rFrame.GetVariables( bArg, bLocals, bStatics, bInScopeOnly ); - const MIuint nArgs = listArg.GetSize(); - for( MIuint i = 0; bOk && (i < nArgs); i++ ) - { - lldb::SBValue value = listArg.GetValueAtIndex( i ); - bOk = GetVariableInfo( nMaxRecusiveDepth, value, false, vwrMiValueList, nCurrentRecursiveDepth ); - } - - return bOk; + bool bOk = MIstatus::success; + lldb::SBFrame &rFrame = const_cast(vrFrame); + + const bool bArg = (vMaskVarTypes & eVariableType_Arguments); + const bool bLocals = (vMaskVarTypes & eVariableType_Locals); + const bool bStatics = (vMaskVarTypes & eVariableType_Statics); + const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope); + const MIuint nMaxRecusiveDepth = 10; + MIuint nCurrentRecursiveDepth = 0; + lldb::SBValueList listArg = rFrame.GetVariables(bArg, bLocals, bStatics, bInScopeOnly); + const MIuint nArgs = listArg.GetSize(); + for (MIuint i = 0; bOk && (i < nArgs); i++) + { + lldb::SBValue value = listArg.GetValueAtIndex(i); + bOk = GetVariableInfo(nMaxRecusiveDepth, value, false, vwrMiValueList, nCurrentRecursiveDepth); + } + + return bOk; } // *** Do not refactor this function to be one function with same name as it can break more than // *** than one stack type command //++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the -// tuple type object past in. -// Type: Method. -// Args: vrFrame - (R) LLDB thread object. -// vMaskVarTypes - (R) 0x1000 = arguments, -// 0x0100 = locals, -// 0x0010 = statics, -// 0x0001 = in scope only. -// vwrMIValueList - (W) MI value list object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Form MI partial response by appending more MI value type objects to the +// tuple type object past in. +// Type: Method. +// Args: vrFrame - (R) LLDB thread object. +// vMaskVarTypes - (R) Construed according to VariableType_e. +// vwrMIValueList - (W) MI value list object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo3( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList ) +bool +CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo3(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes, + CMICmnMIValueList &vwrMiValueList) { - bool bOk = MIstatus::success; - lldb::SBFrame & rFrame = const_cast< lldb::SBFrame & >( vrFrame ); - - const bool bArg = (vMaskVarTypes & 0x1000); - const bool bLocals = (vMaskVarTypes & 0x0100); - const bool bStatics = (vMaskVarTypes & 0x0010); - const bool bInScopeOnly = (vMaskVarTypes & 0x0001); - const MIuint nMaxRecusiveDepth = 10; - MIuint nCurrentRecursiveDepth = 0; - lldb::SBValueList listArg = rFrame.GetVariables( bArg, bLocals, bStatics, bInScopeOnly ); - const MIuint nArgs = listArg.GetSize(); - for( MIuint i = 0; bOk && (i < nArgs); i++ ) - { - lldb::SBValue value = listArg.GetValueAtIndex( i ); - bOk = GetVariableInfo2( nMaxRecusiveDepth, value, false, vwrMiValueList, nCurrentRecursiveDepth ); - } - - return bOk; + bool bOk = MIstatus::success; + lldb::SBFrame &rFrame = const_cast(vrFrame); + + const bool bArg = (vMaskVarTypes & eVariableType_Arguments); + const bool bLocals = (vMaskVarTypes & eVariableType_Locals); + const bool bStatics = (vMaskVarTypes & eVariableType_Statics); + const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope); + const MIuint nMaxRecusiveDepth = 10; + MIuint nCurrentRecursiveDepth = 0; + lldb::SBValueList listArg = rFrame.GetVariables(bArg, bLocals, bStatics, bInScopeOnly); + const MIuint nArgs = listArg.GetSize(); + for (MIuint i = 0; bOk && (i < nArgs); i++) + { + lldb::SBValue value = listArg.GetValueAtIndex(i); + bOk = GetVariableInfo2(nMaxRecusiveDepth, value, false, vwrMiValueList, nCurrentRecursiveDepth); + } + + return bOk; } // *** Do not refactor this function to be one function with same name as it can break more than // *** than one stack type command //++ ------------------------------------------------------------------------------------ -// Details: Extract the value's name and value or recurse into child value object. -// Type: Method. -// Args: vnMaxDepth - (R) The max recursive depth for this function. -// vrValue - (R) LLDB value object. -// vbIsChildValue - (R) True = Value object is a child of a higher Value object, -// - False = Value object not a child. -// vwrMIValueList - (W) MI value list object. -// vnDepth - (RW) The current recursive depth of this function. -// // Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Extract the value's name and value or recurse into child value object. +// Type: Method. +// Args: vnMaxDepth - (R) The max recursive depth for this function. +// vrValue - (R) LLDB value object. +// vbIsChildValue - (R) True = Value object is a child of a higher Value object, +// - False = Value object not a child. +// vwrMIValueList - (W) MI value list object. +// vnDepth - (RW) The current recursive depth of this function. +// // Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::GetVariableInfo( const MIuint vnMaxDepth, const lldb::SBValue & vrValue, const bool vbIsChildValue, CMICmnMIValueList & vwrMiValueList, MIuint & vrwnDepth ) +bool +CMICmnLLDBDebugSessionInfo::GetVariableInfo(const MIuint vnMaxDepth, const lldb::SBValue &vrValue, const bool vbIsChildValue, + CMICmnMIValueList &vwrMiValueList, MIuint &vrwnDepth) { - // *** Update GetVariableInfo2() with any code changes here *** - - // Check recursive depth - if( vrwnDepth >= vnMaxDepth ) - return MIstatus::success; - - bool bOk = MIstatus::success; - lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValue ); - const CMICmnLLDBUtilSBValue utilValue( vrValue, true ); - CMICmnMIValueTuple miValueTuple; - const MIchar * pName = rValue.GetName(); MIunused( pName ); - const bool bIsPointerType = rValue.GetType().IsPointerType(); - const MIuint nChildren = rValue.GetNumChildren(); - if( nChildren == 0 ) - { - if( vbIsChildValue ) - { - if( utilValue.IsCharType() ) - { - // For char types and try to form text string - const CMICmnMIValueConst miValueConst( utilValue.GetValue().c_str(), true ); - miValueTuple.Add( miValueConst, true ); - } - else - { - // For composite types - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%s = %s", utilValue.GetName().c_str(), utilValue.GetValue().c_str() ), true ); - miValueTuple.Add( miValueConst, true ); - } - return vwrMiValueList.Add( CMICmnMIValueConst( miValueTuple.ExtractContentNoBrackets(), true ) ); - } - else - { - // Basic types - const CMICmnMIValueConst miValueConst( utilValue.GetName() ); - const CMICmnMIValueResult miValueResult( "name", miValueConst ); - miValueTuple.Add( miValueResult ); - const CMICmnMIValueConst miValueConst2( utilValue.GetValue() ); - const CMICmnMIValueResult miValueResult2( "value", miValueConst2 ); - miValueTuple.Add( miValueResult2 ); - return vwrMiValueList.Add( miValueTuple ); - } - } - else if( bIsPointerType && utilValue.IsChildCharType() ) - { - // Append string text to the parent value information - const CMICmnMIValueConst miValueConst( utilValue.GetName() ); - const CMICmnMIValueResult miValueResult( "name", miValueConst ); - miValueTuple.Add( miValueResult ); - - const CMIUtilString & rText( utilValue.GetChildValueCString() ); - if( rText.empty() ) - { - const CMICmnMIValueConst miValueConst( utilValue.GetValue() ); - const CMICmnMIValueResult miValueResult( "value", miValueConst ); - miValueTuple.Add( miValueResult ); - } - else - { - if( utilValue.IsValueUnknown() ) - { - const CMICmnMIValueConst miValueConst( rText ); - const CMICmnMIValueResult miValueResult( "value", miValueConst ); - miValueTuple.Add( miValueResult ); - } - else - { - // Note code that has const in will not show the text suffix to the string pointer - // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this - // but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%s %s", utilValue.GetValue().c_str(), rText.c_str() ) ); - const CMICmnMIValueResult miValueResult( "value", miValueConst ); - miValueTuple.Add( miValueResult ); - } - } - return vwrMiValueList.Add( miValueTuple ); - } - else if( bIsPointerType ) - { - if( vbIsChildValue ) - { - // For composite types - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%s = %s", utilValue.GetName().c_str(), utilValue.GetValue().c_str() ), true ); - miValueTuple.Add( miValueConst, true ); - return vwrMiValueList.Add( CMICmnMIValueConst( miValueTuple.ExtractContentNoBrackets(), true ) ); - } - else - { - // Basic types - const CMICmnMIValueConst miValueConst( utilValue.GetName() ); - const CMICmnMIValueResult miValueResult( "name", miValueConst ); - miValueTuple.Add( miValueResult ); - const CMICmnMIValueConst miValueConst2( utilValue.GetValue() ); - const CMICmnMIValueResult miValueResult2( "value", miValueConst2 ); - miValueTuple.Add( miValueResult2 ); - return vwrMiValueList.Add( miValueTuple ); - } - } - else - { - // Build parent child composite types - CMICmnMIValueList miValueList( true ); - for( MIuint i = 0; bOk && (i < nChildren); i++ ) - { - lldb::SBValue member = rValue.GetChildAtIndex( i ); - bOk = GetVariableInfo( vnMaxDepth, member, true, miValueList, ++vrwnDepth ); - } - const CMICmnMIValueConst miValueConst( utilValue.GetName() ); - const CMICmnMIValueResult miValueResult( "name", miValueConst ); - miValueTuple.Add( miValueResult ); - const CMICmnMIValueConst miValueConst2( CMIUtilString::Format( "{%s}", miValueList.ExtractContentNoBrackets().c_str() ) ); - const CMICmnMIValueResult miValueResult2( "value", miValueConst2 ); - miValueTuple.Add( miValueResult2 ); - return vwrMiValueList.Add( miValueTuple ); - } + // *** Update GetVariableInfo2() with any code changes here *** + + // Check recursive depth + if (vrwnDepth >= vnMaxDepth) + return MIstatus::success; + + bool bOk = MIstatus::success; + lldb::SBValue &rValue = const_cast(vrValue); + const CMICmnLLDBUtilSBValue utilValue(vrValue, true); + CMICmnMIValueTuple miValueTuple; + const MIchar *pName = rValue.GetName(); + MIunused(pName); + const bool bIsPointerType = rValue.GetType().IsPointerType(); + const MIuint nChildren = rValue.GetNumChildren(); + if (nChildren == 0) + { + if (vbIsChildValue) + { + if (utilValue.IsCharType()) + { + // For char types and try to form text string + const CMICmnMIValueConst miValueConst(utilValue.GetValue().c_str(), true); + miValueTuple.Add(miValueConst, true); + } + else + { + // For composite types + const CMICmnMIValueConst miValueConst( + CMIUtilString::Format("%s = %s", utilValue.GetName().c_str(), utilValue.GetValue().c_str()), true); + miValueTuple.Add(miValueConst, true); + } + return vwrMiValueList.Add(CMICmnMIValueConst(miValueTuple.ExtractContentNoBrackets(), true)); + } + else + { + // Basic types + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + miValueTuple.Add(miValueResult); + const CMICmnMIValueConst miValueConst2(utilValue.GetValue()); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + return vwrMiValueList.Add(miValueTuple); + } + } + else if (bIsPointerType && utilValue.IsChildCharType()) + { + // Append string text to the parent value information + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + miValueTuple.Add(miValueResult); + + const CMIUtilString &rText(utilValue.GetChildValueCString()); + if (rText.empty()) + { + const CMICmnMIValueConst miValueConst(utilValue.GetValue()); + const CMICmnMIValueResult miValueResult("value", miValueConst); + miValueTuple.Add(miValueResult); + } + else + { + if (utilValue.IsValueUnknown()) + { + const CMICmnMIValueConst miValueConst(rText); + const CMICmnMIValueResult miValueResult("value", miValueConst); + miValueTuple.Add(miValueResult); + } + else + { + // Note code that has const in will not show the text suffix to the string pointer + // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this + // but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%s %s", utilValue.GetValue().c_str(), rText.c_str())); + const CMICmnMIValueResult miValueResult("value", miValueConst); + miValueTuple.Add(miValueResult); + } + } + return vwrMiValueList.Add(miValueTuple); + } + else if (bIsPointerType) + { + if (vbIsChildValue) + { + // For composite types + const CMICmnMIValueConst miValueConst( + CMIUtilString::Format("%s = %s", utilValue.GetName().c_str(), utilValue.GetValue().c_str()), true); + miValueTuple.Add(miValueConst, true); + return vwrMiValueList.Add(CMICmnMIValueConst(miValueTuple.ExtractContentNoBrackets(), true)); + } + else + { + // Basic types + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + miValueTuple.Add(miValueResult); + const CMICmnMIValueConst miValueConst2(utilValue.GetValue()); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + return vwrMiValueList.Add(miValueTuple); + } + } + else + { + // Build parent child composite types + CMICmnMIValueList miValueList(true); + for (MIuint i = 0; bOk && (i < nChildren); i++) + { + lldb::SBValue member = rValue.GetChildAtIndex(i); + bOk = GetVariableInfo(vnMaxDepth, member, true, miValueList, ++vrwnDepth); + } + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + miValueTuple.Add(miValueResult); + const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("{%s}", miValueList.ExtractContentNoBrackets().c_str())); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + return vwrMiValueList.Add(miValueTuple); + } } // *** Do not refactor this function to be one function with same name as it can break more than // *** than one stack type command //++ ------------------------------------------------------------------------------------ -// Details: Extract the value's name and value or recurse into child value object. -// Type: Method. -// Args: vnMaxDepth - (R) The max recursive depth for this function. -// vrValue - (R) LLDB value object. -// vbIsChildValue - (R) True = Value object is a child of a higher Value object, -// - False = Value object not a child. -// vwrMIValueList - (W) MI value list object. -// vnDepth - (RW) The current recursive depth of this function. -// // Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Extract the value's name and value or recurse into child value object. +// Type: Method. +// Args: vnMaxDepth - (R) The max recursive depth for this function. +// vrValue - (R) LLDB value object. +// vbIsChildValue - (R) True = Value object is a child of a higher Value object, +// - False = Value object not a child. +// vwrMIValueList - (W) MI value list object. +// vnDepth - (RW) The current recursive depth of this function. +// // Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::GetVariableInfo2( const MIuint vnMaxDepth, const lldb::SBValue & vrValue, const bool vbIsChildValue, CMICmnMIValueList & vwrMiValueList, MIuint & vrwnDepth ) +bool +CMICmnLLDBDebugSessionInfo::GetVariableInfo2(const MIuint vnMaxDepth, const lldb::SBValue &vrValue, const bool vbIsChildValue, + CMICmnMIValueList &vwrMiValueList, MIuint &vrwnDepth) { - // *** Update GetVariableInfo() with any code changes here *** - - // Check recursive depth - if( vrwnDepth >= vnMaxDepth ) - return MIstatus::success; - - bool bOk = MIstatus::success; - lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValue ); - const CMICmnLLDBUtilSBValue utilValue( vrValue, true ); - CMICmnMIValueTuple miValueTuple; - const MIchar * pName = rValue.GetName(); MIunused( pName ); - const MIuint nChildren = rValue.GetNumChildren(); - if( nChildren == 0 ) - { - if( vbIsChildValue && utilValue.IsCharType() ) - { - // For char types and try to form text string - const CMICmnMIValueConst miValueConst( utilValue.GetValue().c_str(), true ); - miValueTuple.Add( miValueConst, true ); - return vwrMiValueList.Add( CMICmnMIValueConst( miValueTuple.ExtractContentNoBrackets(), true ) ); - } - else - { - // Basic types - const CMICmnMIValueConst miValueConst( utilValue.GetName() ); - const CMICmnMIValueResult miValueResult( "name", miValueConst ); - miValueTuple.Add( miValueResult ); - const CMICmnMIValueConst miValueConst2( utilValue.GetValue() ); - const CMICmnMIValueResult miValueResult2( "value", miValueConst2 ); - miValueTuple.Add( miValueResult2 ); - return vwrMiValueList.Add( miValueTuple ); - } - } - else if( utilValue.IsChildCharType() ) - { - // Append string text to the parent value information - const CMICmnMIValueConst miValueConst( utilValue.GetName() ); - const CMICmnMIValueResult miValueResult( "name", miValueConst ); - miValueTuple.Add( miValueResult ); - - const CMIUtilString & rText( utilValue.GetChildValueCString() ); - if( rText.empty() ) - { - const CMICmnMIValueConst miValueConst( utilValue.GetValue() ); - const CMICmnMIValueResult miValueResult( "value", miValueConst ); - miValueTuple.Add( miValueResult ); - } - else - { - if( utilValue.IsValueUnknown() ) - { - const CMICmnMIValueConst miValueConst( rText ); - const CMICmnMIValueResult miValueResult( "value", miValueConst ); - miValueTuple.Add( miValueResult ); - } - else - { - // Note code that has const in will not show the text suffix to the string pointer - // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this - // but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%s %s", utilValue.GetValue().c_str(), rText.c_str() ) ); - const CMICmnMIValueResult miValueResult( "value", miValueConst ); - miValueTuple.Add( miValueResult ); - } - } - return vwrMiValueList.Add( miValueTuple ); - } - else - { - // Build parent child composite types - CMICmnMIValueList miValueList( true ); - for( MIuint i = 0; bOk && (i < nChildren); i++ ) - { - lldb::SBValue member = rValue.GetChildAtIndex( i ); - bOk = GetVariableInfo( vnMaxDepth, member, true, miValueList, ++vrwnDepth ); - } - const CMICmnMIValueConst miValueConst( utilValue.GetName() ); - const CMICmnMIValueResult miValueResult( "name", miValueConst ); - miValueTuple.Add( miValueResult ); - const CMICmnMIValueConst miValueConst2( CMIUtilString::Format( "{%s}", miValueList.ExtractContentNoBrackets().c_str() ) ); - const CMICmnMIValueResult miValueResult2( "value", miValueConst2 ); - miValueTuple.Add( miValueResult2 ); - return vwrMiValueList.Add( miValueTuple ); - } + // *** Update GetVariableInfo() with any code changes here *** + + // Check recursive depth + if (vrwnDepth >= vnMaxDepth) + return MIstatus::success; + + bool bOk = MIstatus::success; + lldb::SBValue &rValue = const_cast(vrValue); + const CMICmnLLDBUtilSBValue utilValue(vrValue, true); + CMICmnMIValueTuple miValueTuple; + const MIchar *pName = rValue.GetName(); + MIunused(pName); + const MIuint nChildren = rValue.GetNumChildren(); + if (nChildren == 0) + { + if (vbIsChildValue && utilValue.IsCharType()) + { + // For char types and try to form text string + const CMICmnMIValueConst miValueConst(utilValue.GetValue().c_str(), true); + miValueTuple.Add(miValueConst, true); + return vwrMiValueList.Add(CMICmnMIValueConst(miValueTuple.ExtractContentNoBrackets(), true)); + } + else + { + // Basic types + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + miValueTuple.Add(miValueResult); + const CMICmnMIValueConst miValueConst2(utilValue.GetValue()); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + return vwrMiValueList.Add(miValueTuple); + } + } + else if (utilValue.IsChildCharType()) + { + // Append string text to the parent value information + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + miValueTuple.Add(miValueResult); + + const CMIUtilString &rText(utilValue.GetChildValueCString()); + if (rText.empty()) + { + const CMICmnMIValueConst miValueConst(utilValue.GetValue()); + const CMICmnMIValueResult miValueResult("value", miValueConst); + miValueTuple.Add(miValueResult); + } + else + { + if (utilValue.IsValueUnknown()) + { + const CMICmnMIValueConst miValueConst(rText); + const CMICmnMIValueResult miValueResult("value", miValueConst); + miValueTuple.Add(miValueResult); + } + else + { + // Note code that has const in will not show the text suffix to the string pointer + // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this + // but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%s %s", utilValue.GetValue().c_str(), rText.c_str())); + const CMICmnMIValueResult miValueResult("value", miValueConst); + miValueTuple.Add(miValueResult); + } + } + return vwrMiValueList.Add(miValueTuple); + } + else + { + // Build parent child composite types + CMICmnMIValueList miValueList(true); + for (MIuint i = 0; bOk && (i < nChildren); i++) + { + lldb::SBValue member = rValue.GetChildAtIndex(i); + bOk = GetVariableInfo(vnMaxDepth, member, true, miValueList, ++vrwnDepth); + } + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + miValueTuple.Add(miValueResult); + const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("{%s}", miValueList.ExtractContentNoBrackets().c_str())); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + return vwrMiValueList.Add(miValueTuple); + } } //++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the -// tuple type object past in. -// Type: Method. -// Args: vrThread - (R) LLDB thread object. -// vwrMIValueTuple - (W) MI value tuple object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Form MI partial response by appending more MI value type objects to the +// tuple type object past in. +// Type: Method. +// Args: vrThread - (R) LLDB thread object. +// vwrMIValueTuple - (W) MI value tuple object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo( const lldb::SBThread & vrThread, const MIuint vnLevel, CMICmnMIValueTuple & vwrMiValueTuple ) +bool +CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo(const lldb::SBThread &vrThread, const MIuint vnLevel, + CMICmnMIValueTuple &vwrMiValueTuple) { - lldb::SBThread & rThread = const_cast< lldb::SBThread & >( vrThread ); - - lldb::SBFrame frame = rThread.GetFrameAtIndex( vnLevel ); - lldb::addr_t pc = 0; - CMIUtilString fnName; - CMIUtilString fileName; - CMIUtilString path; - MIuint nLine = 0; - if( !GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) ) - return MIstatus::failure; - - // MI print "{level=\"0\",addr=\"0x%08llx\",func=\"%s\",file=\"%s\",fullname=\"%s\",line=\"%d\"}" - const CMIUtilString strLevel( CMIUtilString::Format( "%d", vnLevel ) ); - const CMICmnMIValueConst miValueConst( strLevel ); - const CMICmnMIValueResult miValueResult( "level", miValueConst ); - CMICmnMIValueTuple miValueTuple( miValueResult ); - if( !MIResponseFormFrameInfo( pc, fnName, fileName, path, nLine, miValueTuple ) ) - return MIstatus::failure; - - vwrMiValueTuple = miValueTuple; - - return MIstatus::success; + lldb::SBThread &rThread = const_cast(vrThread); + + lldb::SBFrame frame = rThread.GetFrameAtIndex(vnLevel); + lldb::addr_t pc = 0; + CMIUtilString fnName; + CMIUtilString fileName; + CMIUtilString path; + MIuint nLine = 0; + if (!GetFrameInfo(frame, pc, fnName, fileName, path, nLine)) + return MIstatus::failure; + + // MI print "{level=\"0\",addr=\"0x%08llx\",func=\"%s\",file=\"%s\",fullname=\"%s\",line=\"%d\"}" + const CMIUtilString strLevel(CMIUtilString::Format("%d", vnLevel)); + const CMICmnMIValueConst miValueConst(strLevel); + const CMICmnMIValueResult miValueResult("level", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + if (!MIResponseFormFrameInfo(pc, fnName, fileName, path, nLine, miValueTuple)) + return MIstatus::failure; + + vwrMiValueTuple = miValueTuple; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the frame information from LLDB frame object. -// Type: Method. -// Args: vrFrame - (R) LLDB thread object. -// vPc - (W) Address number. -// vFnName - (W) Function name. -// vFileName - (W) File name text. -// vPath - (W) Full file name and path text. -// vnLine - (W) File line number. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieve the frame information from LLDB frame object. +// Type: Method. +// Args: vrFrame - (R) LLDB thread object. +// vPc - (W) Address number. +// vFnName - (W) Function name. +// vFileName - (W) File name text. +// vPath - (W) Full file name and path text. +// vnLine - (W) File line number. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::GetFrameInfo( const lldb::SBFrame & vrFrame, lldb::addr_t & vwPc, CMIUtilString & vwFnName, CMIUtilString & vwFileName, CMIUtilString & vwPath, MIuint & vwnLine ) +bool +CMICmnLLDBDebugSessionInfo::GetFrameInfo(const lldb::SBFrame &vrFrame, lldb::addr_t &vwPc, CMIUtilString &vwFnName, + CMIUtilString &vwFileName, CMIUtilString &vwPath, MIuint &vwnLine) { - lldb::SBFrame & rFrame = const_cast< lldb::SBFrame & >( vrFrame ); - - static char pBuffer[ MAX_PATH ]; - const MIuint nBytes = rFrame.GetLineEntry().GetFileSpec().GetPath( &pBuffer[ 0 ], sizeof( pBuffer ) ); MIunused( nBytes ); - CMIUtilString strResolvedPath( &pBuffer[ 0 ] ); - const MIchar * pUnkwn = "??"; - if( !ResolvePath( pUnkwn, strResolvedPath ) ) - return MIstatus::failure; - vwPath = strResolvedPath; - - vwPc = rFrame.GetPC(); - - const MIchar * pFnName = rFrame.GetFunctionName(); - vwFnName = (pFnName != nullptr) ? pFnName : pUnkwn; - - const MIchar * pFileName = rFrame.GetLineEntry().GetFileSpec().GetFilename(); - vwFileName = (pFileName != nullptr) ? pFileName : pUnkwn; - - vwnLine = rFrame.GetLineEntry().GetLine(); - - return MIstatus::success; + lldb::SBFrame &rFrame = const_cast(vrFrame); + + static char pBuffer[MAX_PATH]; + const MIuint nBytes = rFrame.GetLineEntry().GetFileSpec().GetPath(&pBuffer[0], sizeof(pBuffer)); + MIunused(nBytes); + CMIUtilString strResolvedPath(&pBuffer[0]); + const MIchar *pUnkwn = "??"; + if (!ResolvePath(pUnkwn, strResolvedPath)) + return MIstatus::failure; + vwPath = strResolvedPath; + + vwPc = rFrame.GetPC(); + + const MIchar *pFnName = rFrame.GetFunctionName(); + vwFnName = (pFnName != nullptr) ? pFnName : pUnkwn; + + const MIchar *pFileName = rFrame.GetLineEntry().GetFileSpec().GetFilename(); + vwFileName = (pFileName != nullptr) ? pFileName : pUnkwn; + + vwnLine = rFrame.GetLineEntry().GetLine(); + + return MIstatus::success; } - + //++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the -// tuple type object past in. -// Type: Method. -// Args: vPc - (R) Address number. -// vFnName - (R) Function name. -// vFileName - (R) File name text. -// vPath - (R) Full file name and path text. -// vnLine - (R) File line number. -// vwrMIValueTuple - (W) MI value tuple object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Form MI partial response by appending more MI value type objects to the +// tuple type object past in. +// Type: Method. +// Args: vPc - (R) Address number. +// vFnName - (R) Function name. +// vFileName - (R) File name text. +// vPath - (R) Full file name and path text. +// vnLine - (R) File line number. +// vwrMIValueTuple - (W) MI value tuple object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo( const lldb::addr_t vPc, const CMIUtilString & vFnName, const CMIUtilString & vFileName, const CMIUtilString & vPath, const MIuint vnLine, CMICmnMIValueTuple & vwrMiValueTuple ) +bool +CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo(const lldb::addr_t vPc, const CMIUtilString &vFnName, const CMIUtilString &vFileName, + const CMIUtilString &vPath, const MIuint vnLine, CMICmnMIValueTuple &vwrMiValueTuple) { - const CMIUtilString strAddr( CMIUtilString::Format( "0x%08llx", vPc ) ); - const CMICmnMIValueConst miValueConst2( strAddr ); - const CMICmnMIValueResult miValueResult2( "addr", miValueConst2 ); - if( !vwrMiValueTuple.Add( miValueResult2 ) ) - return MIstatus::failure; - const CMICmnMIValueConst miValueConst3( vFnName ); - const CMICmnMIValueResult miValueResult3( "func", miValueConst3 ); - if( !vwrMiValueTuple.Add( miValueResult3 ) ) - return MIstatus::failure; - const CMICmnMIValueConst miValueConst5( vFileName ); - const CMICmnMIValueResult miValueResult5( "file", miValueConst5 ); - if( !vwrMiValueTuple.Add( miValueResult5 ) ) - return MIstatus::failure; - const CMICmnMIValueConst miValueConst6( vPath ); - const CMICmnMIValueResult miValueResult6( "fullname", miValueConst6 ); - if( !vwrMiValueTuple.Add( miValueResult6 ) ) - return MIstatus::failure; - const CMIUtilString strLine( CMIUtilString::Format( "%d", vnLine ) ); - const CMICmnMIValueConst miValueConst7( strLine ); - const CMICmnMIValueResult miValueResult7( "line", miValueConst7 ); - if( !vwrMiValueTuple.Add( miValueResult7 ) ) - return MIstatus::failure; - - return MIstatus::success; + const CMIUtilString strAddr(CMIUtilString::Format("0x%08llx", vPc)); + const CMICmnMIValueConst miValueConst2(strAddr); + const CMICmnMIValueResult miValueResult2("addr", miValueConst2); + if (!vwrMiValueTuple.Add(miValueResult2)) + return MIstatus::failure; + const CMICmnMIValueConst miValueConst3(vFnName); + const CMICmnMIValueResult miValueResult3("func", miValueConst3); + if (!vwrMiValueTuple.Add(miValueResult3)) + return MIstatus::failure; + const CMICmnMIValueConst miValueConst5(vFileName); + const CMICmnMIValueResult miValueResult5("file", miValueConst5); + if (!vwrMiValueTuple.Add(miValueResult5)) + return MIstatus::failure; + const CMICmnMIValueConst miValueConst6(vPath); + const CMICmnMIValueResult miValueResult6("fullname", miValueConst6); + if (!vwrMiValueTuple.Add(miValueResult6)) + return MIstatus::failure; + const CMIUtilString strLine(CMIUtilString::Format("%d", vnLine)); + const CMICmnMIValueConst miValueConst7(strLine); + const CMICmnMIValueResult miValueResult7("line", miValueConst7); + if (!vwrMiValueTuple.Add(miValueResult7)) + return MIstatus::failure; + + return MIstatus::success; } // Todo: Refactor maybe to so only one function with this name, but not just yet //++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the -// tuple type object past in. -// Type: Method. -// Args: vPc - (R) Address number. -// vArgInfo - (R) Args information in MI response form. -// vFnName - (R) Function name. -// vFileName - (R) File name text. -// vPath - (R) Full file name and path text. -// vnLine - (R) File line number. -// vwrMIValueTuple - (W) MI value tuple object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Form MI partial response by appending more MI value type objects to the +// tuple type object past in. +// Type: Method. +// Args: vPc - (R) Address number. +// vArgInfo - (R) Args information in MI response form. +// vFnName - (R) Function name. +// vFileName - (R) File name text. +// vPath - (R) Full file name and path text. +// vnLine - (R) File line number. +// vwrMIValueTuple - (W) MI value tuple object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo2( const lldb::addr_t vPc, const CMIUtilString & vArgInfo, const CMIUtilString & vFnName, const CMIUtilString & vFileName, const CMIUtilString & vPath, const MIuint vnLine, CMICmnMIValueTuple & vwrMiValueTuple ) +bool +CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo2(const lldb::addr_t vPc, const CMIUtilString &vArgInfo, const CMIUtilString &vFnName, + const CMIUtilString &vFileName, const CMIUtilString &vPath, const MIuint vnLine, + CMICmnMIValueTuple &vwrMiValueTuple) { - const CMIUtilString strAddr( CMIUtilString::Format( "0x%08llx", vPc ) ); - const CMICmnMIValueConst miValueConst2( strAddr ); - const CMICmnMIValueResult miValueResult2( "addr", miValueConst2 ); - if( !vwrMiValueTuple.Add( miValueResult2 ) ) - return MIstatus::failure; - const CMICmnMIValueConst miValueConst3( vFnName ); - const CMICmnMIValueResult miValueResult3( "func", miValueConst3 ); - if( !vwrMiValueTuple.Add( miValueResult3 ) ) - return MIstatus::failure; - const CMICmnMIValueConst miValueConst4( vArgInfo, true ); - const CMICmnMIValueResult miValueResult4( "args", miValueConst4 ); - if( !vwrMiValueTuple.Add( miValueResult4 ) ) - return MIstatus::failure; - const CMICmnMIValueConst miValueConst5( vFileName ); - const CMICmnMIValueResult miValueResult5( "file", miValueConst5 ); - if( !vwrMiValueTuple.Add( miValueResult5 ) ) - return MIstatus::failure; - const CMICmnMIValueConst miValueConst6( vPath ); - const CMICmnMIValueResult miValueResult6( "fullname", miValueConst6 ); - if( !vwrMiValueTuple.Add( miValueResult6 ) ) - return MIstatus::failure; - const CMIUtilString strLine( CMIUtilString::Format( "%d", vnLine ) ); - const CMICmnMIValueConst miValueConst7( strLine ); - const CMICmnMIValueResult miValueResult7( "line", miValueConst7 ); - if( !vwrMiValueTuple.Add( miValueResult7 ) ) - return MIstatus::failure; - - return MIstatus::success; + const CMIUtilString strAddr(CMIUtilString::Format("0x%08llx", vPc)); + const CMICmnMIValueConst miValueConst2(strAddr); + const CMICmnMIValueResult miValueResult2("addr", miValueConst2); + if (!vwrMiValueTuple.Add(miValueResult2)) + return MIstatus::failure; + const CMICmnMIValueConst miValueConst3(vFnName); + const CMICmnMIValueResult miValueResult3("func", miValueConst3); + if (!vwrMiValueTuple.Add(miValueResult3)) + return MIstatus::failure; + const CMICmnMIValueConst miValueConst4(vArgInfo, true); + const CMICmnMIValueResult miValueResult4("args", miValueConst4); + if (!vwrMiValueTuple.Add(miValueResult4)) + return MIstatus::failure; + const CMICmnMIValueConst miValueConst5(vFileName); + const CMICmnMIValueResult miValueResult5("file", miValueConst5); + if (!vwrMiValueTuple.Add(miValueResult5)) + return MIstatus::failure; + const CMICmnMIValueConst miValueConst6(vPath); + const CMICmnMIValueResult miValueResult6("fullname", miValueConst6); + if (!vwrMiValueTuple.Add(miValueResult6)) + return MIstatus::failure; + const CMIUtilString strLine(CMIUtilString::Format("%d", vnLine)); + const CMICmnMIValueConst miValueConst7(strLine); + const CMICmnMIValueResult miValueResult7("line", miValueConst7); + if (!vwrMiValueTuple.Add(miValueResult7)) + return MIstatus::failure; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the -// tuple type object past in. -// Type: Method. -// Args: vrBrkPtInfo - (R) Break point information object. -// vwrMIValueTuple - (W) MI value tuple object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Form MI partial response by appending more MI value type objects to the +// tuple type object past in. +// Type: Method. +// Args: vrBrkPtInfo - (R) Break point information object. +// vwrMIValueTuple - (W) MI value tuple object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtFrameInfo( const SBrkPtInfo & vrBrkPtInfo, CMICmnMIValueTuple & vwrMiValueTuple ) +bool +CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtFrameInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple) { - const CMIUtilString strAddr( CMIUtilString::Format( "0x%08llx", vrBrkPtInfo.m_pc ) ); - const CMICmnMIValueConst miValueConst2( strAddr ); - const CMICmnMIValueResult miValueResult2( "addr", miValueConst2 ); - if( !vwrMiValueTuple.Add( miValueResult2 ) ) - return MIstatus::failure; - const CMICmnMIValueConst miValueConst3( vrBrkPtInfo.m_fnName ); - const CMICmnMIValueResult miValueResult3( "func", miValueConst3 ); - if( !vwrMiValueTuple.Add( miValueResult3 ) ) - return MIstatus::failure; - const CMICmnMIValueConst miValueConst5( vrBrkPtInfo.m_fileName ); - const CMICmnMIValueResult miValueResult5( "file", miValueConst5 ); - if( !vwrMiValueTuple.Add( miValueResult5 ) ) - return MIstatus::failure; - const CMIUtilString strN5 = CMIUtilString::Format( "%s/%s", vrBrkPtInfo.m_path.c_str(), vrBrkPtInfo.m_fileName.c_str() ); - const CMICmnMIValueConst miValueConst6( strN5 ); - const CMICmnMIValueResult miValueResult6( "fullname", miValueConst6 ); - if( !vwrMiValueTuple.Add( miValueResult6 ) ) - return MIstatus::failure; - const CMIUtilString strLine( CMIUtilString::Format( "%d", vrBrkPtInfo.m_nLine ) ); - const CMICmnMIValueConst miValueConst7( strLine ); - const CMICmnMIValueResult miValueResult7( "line", miValueConst7 ); - if( !vwrMiValueTuple.Add( miValueResult7 ) ) - return MIstatus::failure; - - return MIstatus::success; + const CMIUtilString strAddr(CMIUtilString::Format("0x%08llx", vrBrkPtInfo.m_pc)); + const CMICmnMIValueConst miValueConst2(strAddr); + const CMICmnMIValueResult miValueResult2("addr", miValueConst2); + if (!vwrMiValueTuple.Add(miValueResult2)) + return MIstatus::failure; + const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_fnName); + const CMICmnMIValueResult miValueResult3("func", miValueConst3); + if (!vwrMiValueTuple.Add(miValueResult3)) + return MIstatus::failure; + const CMICmnMIValueConst miValueConst5(vrBrkPtInfo.m_fileName); + const CMICmnMIValueResult miValueResult5("file", miValueConst5); + if (!vwrMiValueTuple.Add(miValueResult5)) + return MIstatus::failure; + const CMIUtilString strN5 = CMIUtilString::Format("%s/%s", vrBrkPtInfo.m_path.c_str(), vrBrkPtInfo.m_fileName.c_str()); + const CMICmnMIValueConst miValueConst6(strN5); + const CMICmnMIValueResult miValueResult6("fullname", miValueConst6); + if (!vwrMiValueTuple.Add(miValueResult6)) + return MIstatus::failure; + const CMIUtilString strLine(CMIUtilString::Format("%d", vrBrkPtInfo.m_nLine)); + const CMICmnMIValueConst miValueConst7(strLine); + const CMICmnMIValueResult miValueResult7("line", miValueConst7); + if (!vwrMiValueTuple.Add(miValueResult7)) + return MIstatus::failure; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the -// tuple type object past in. -// Type: Method. -// Args: vrBrkPtInfo - (R) Break point information object. -// vwrMIValueTuple - (W) MI value tuple object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Form MI partial response by appending more MI value type objects to the +// tuple type object past in. +// Type: Method. +// Args: vrBrkPtInfo - (R) Break point information object. +// vwrMIValueTuple - (W) MI value tuple object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtInfo( const SBrkPtInfo & vrBrkPtInfo, CMICmnMIValueTuple & vwrMiValueTuple ) +bool +CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple) { - // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\", func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" - - // "number=" - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", vrBrkPtInfo.m_id ) ); - const CMICmnMIValueResult miValueResult( "number", miValueConst ); - CMICmnMIValueTuple miValueTuple( miValueResult ); - // "type=" - const CMICmnMIValueConst miValueConst2( vrBrkPtInfo.m_strType ); - const CMICmnMIValueResult miValueResult2( "type", miValueConst2 ); - bool bOk = miValueTuple.Add( miValueResult2 ); - // "disp=" - const CMICmnMIValueConst miValueConst3( vrBrkPtInfo.m_bDisp ? "del" : "keep" ); - const CMICmnMIValueResult miValueResult3( "disp", miValueConst3 ); - bOk = bOk && miValueTuple.Add( miValueResult3 ); - // "enabled=" - const CMICmnMIValueConst miValueConst4( vrBrkPtInfo.m_bEnabled ? "y" : "n" ); - const CMICmnMIValueResult miValueResult4( "enabled", miValueConst4 ); - bOk = bOk && miValueTuple.Add( miValueResult4 ); - // "addr=" - // "func=" - // "file=" - // "fullname=" - // "line=" - bOk = bOk && MIResponseFormBrkPtFrameInfo( vrBrkPtInfo, miValueTuple ); - // "pending=" - if( vrBrkPtInfo.m_bPending ) - { - const CMICmnMIValueConst miValueConst( vrBrkPtInfo.m_strOrigLoc ); - const CMICmnMIValueList miValueList( miValueConst ); - const CMICmnMIValueResult miValueResult( "pending", miValueList ); - bOk = bOk && miValueTuple.Add( miValueResult ); - } - if( vrBrkPtInfo.m_bHaveArgOptionThreadGrp ) - { - const CMICmnMIValueConst miValueConst( vrBrkPtInfo.m_strOptThrdGrp ); - const CMICmnMIValueList miValueList( miValueConst ); - const CMICmnMIValueResult miValueResult( "thread-groups", miValueList ); - bOk = bOk && miValueTuple.Add( miValueResult ); - } - // "times=" - const CMICmnMIValueConst miValueConstB( CMIUtilString::Format( "%d", vrBrkPtInfo.m_nTimes ) ); - const CMICmnMIValueResult miValueResultB( "times", miValueConstB ); - bOk = bOk && miValueTuple.Add( miValueResultB ); - // "thread=" - if( vrBrkPtInfo.m_bBrkPtThreadId ) - { - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", vrBrkPtInfo.m_nBrkPtThreadId ) ); - const CMICmnMIValueResult miValueResult( "thread", miValueConst ); - bOk = bOk && miValueTuple.Add( miValueResult ); - } - // "cond=" - if( vrBrkPtInfo.m_bCondition ) - { - const CMICmnMIValueConst miValueConst( vrBrkPtInfo.m_strCondition ); - const CMICmnMIValueResult miValueResult( "cond", miValueConst ); - bOk = bOk && miValueTuple.Add( miValueResult ); - } - // "ignore=" - if( vrBrkPtInfo.m_nIgnore != 0 ) - { - const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", vrBrkPtInfo.m_nIgnore ) ); - const CMICmnMIValueResult miValueResult( "ignore", miValueConst ); - bOk = bOk && miValueTuple.Add( miValueResult ); - } - // "original-location=" - const CMICmnMIValueConst miValueConstC( vrBrkPtInfo.m_strOrigLoc ); - const CMICmnMIValueResult miValueResultC( "original-location", miValueConstC ); - bOk = bOk && miValueTuple.Add( miValueResultC ); - - vwrMiValueTuple = miValueTuple; - - return MIstatus::success; + // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\", + // func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" + + // "number=" + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_id)); + const CMICmnMIValueResult miValueResult("number", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + // "type=" + const CMICmnMIValueConst miValueConst2(vrBrkPtInfo.m_strType); + const CMICmnMIValueResult miValueResult2("type", miValueConst2); + bool bOk = miValueTuple.Add(miValueResult2); + // "disp=" + const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_bDisp ? "del" : "keep"); + const CMICmnMIValueResult miValueResult3("disp", miValueConst3); + bOk = bOk && miValueTuple.Add(miValueResult3); + // "enabled=" + const CMICmnMIValueConst miValueConst4(vrBrkPtInfo.m_bEnabled ? "y" : "n"); + const CMICmnMIValueResult miValueResult4("enabled", miValueConst4); + bOk = bOk && miValueTuple.Add(miValueResult4); + // "addr=" + // "func=" + // "file=" + // "fullname=" + // "line=" + bOk = bOk && MIResponseFormBrkPtFrameInfo(vrBrkPtInfo, miValueTuple); + // "pending=" + if (vrBrkPtInfo.m_bPending) + { + const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOrigLoc); + const CMICmnMIValueList miValueList(miValueConst); + const CMICmnMIValueResult miValueResult("pending", miValueList); + bOk = bOk && miValueTuple.Add(miValueResult); + } + if (vrBrkPtInfo.m_bHaveArgOptionThreadGrp) + { + const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOptThrdGrp); + const CMICmnMIValueList miValueList(miValueConst); + const CMICmnMIValueResult miValueResult("thread-groups", miValueList); + bOk = bOk && miValueTuple.Add(miValueResult); + } + // "times=" + const CMICmnMIValueConst miValueConstB(CMIUtilString::Format("%d", vrBrkPtInfo.m_nTimes)); + const CMICmnMIValueResult miValueResultB("times", miValueConstB); + bOk = bOk && miValueTuple.Add(miValueResultB); + // "thread=" + if (vrBrkPtInfo.m_bBrkPtThreadId) + { + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_nBrkPtThreadId)); + const CMICmnMIValueResult miValueResult("thread", miValueConst); + bOk = bOk && miValueTuple.Add(miValueResult); + } + // "cond=" + if (vrBrkPtInfo.m_bCondition) + { + const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strCondition); + const CMICmnMIValueResult miValueResult("cond", miValueConst); + bOk = bOk && miValueTuple.Add(miValueResult); + } + // "ignore=" + if (vrBrkPtInfo.m_nIgnore != 0) + { + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_nIgnore)); + const CMICmnMIValueResult miValueResult("ignore", miValueConst); + bOk = bOk && miValueTuple.Add(miValueResult); + } + // "original-location=" + const CMICmnMIValueConst miValueConstC(vrBrkPtInfo.m_strOrigLoc); + const CMICmnMIValueResult miValueResultC("original-location", miValueConstC); + bOk = bOk && miValueTuple.Add(miValueResultC); + + vwrMiValueTuple = miValueTuple; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve breakpoint information and write into the given breakpoint information -// object. Note not all possible information is retrieved and so the information -// object may need to be filled in with more information after calling this -// function. Mainly breakpoint location information of information that is -// unlikely to change. -// Type: Method. -// Args: vBrkPt - (R) LLDB break point object. -// vrBrkPtInfo - (W) Break point information object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieve breakpoint information and write into the given breakpoint information +// object. Note not all possible information is retrieved and so the information +// object may need to be filled in with more information after calling this +// function. Mainly breakpoint location information of information that is +// unlikely to change. +// Type: Method. +// Args: vBrkPt - (R) LLDB break point object. +// vrBrkPtInfo - (W) Break point information object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugSessionInfo::GetBrkPtInfo( const lldb::SBBreakpoint & vBrkPt, SBrkPtInfo & vrwBrkPtInfo ) const +bool +CMICmnLLDBDebugSessionInfo::GetBrkPtInfo(const lldb::SBBreakpoint &vBrkPt, SBrkPtInfo &vrwBrkPtInfo) const { - lldb::SBBreakpoint & rBrkPt = const_cast< lldb::SBBreakpoint & >( vBrkPt ); - lldb::SBBreakpointLocation brkPtLoc = rBrkPt.GetLocationAtIndex( 0 ); - lldb::SBAddress brkPtAddr = brkPtLoc.GetAddress(); - lldb::SBSymbolContext symbolCntxt = brkPtAddr.GetSymbolContext( lldb::eSymbolContextEverything ); - const MIchar * pUnkwn = "??"; - lldb::SBModule rModule = symbolCntxt.GetModule(); - const MIchar * pModule = rModule.IsValid() ? rModule.GetFileSpec().GetFilename() : pUnkwn; MIunused( pModule ); - const MIchar * pFile = pUnkwn; - const MIchar * pFn = pUnkwn; - const MIchar * pFilePath = pUnkwn; - size_t nLine = 0; - const size_t nAddr = brkPtAddr.GetLoadAddress( m_lldbTarget ); - - lldb::SBCompileUnit rCmplUnit = symbolCntxt.GetCompileUnit(); - if( rCmplUnit.IsValid() ) - { - lldb::SBFileSpec rFileSpec = rCmplUnit.GetFileSpec(); - pFile = rFileSpec.GetFilename(); - pFilePath = rFileSpec.GetDirectory(); - lldb::SBFunction rFn = symbolCntxt.GetFunction(); - if( rFn.IsValid() ) - pFn = rFn.GetName(); - lldb::SBLineEntry rLnEntry = symbolCntxt.GetLineEntry(); - if( rLnEntry.GetLine() > 0 ) - nLine = rLnEntry.GetLine(); - } - - vrwBrkPtInfo.m_id = vBrkPt.GetID(); - vrwBrkPtInfo.m_strType = "breakpoint"; - vrwBrkPtInfo.m_pc = nAddr; - vrwBrkPtInfo.m_fnName = pFn; - vrwBrkPtInfo.m_fileName = pFile; - vrwBrkPtInfo.m_path = pFilePath; - vrwBrkPtInfo.m_nLine = nLine; - vrwBrkPtInfo.m_nTimes = vBrkPt.GetHitCount(); - - return MIstatus::success; + lldb::SBBreakpoint &rBrkPt = const_cast(vBrkPt); + lldb::SBBreakpointLocation brkPtLoc = rBrkPt.GetLocationAtIndex(0); + lldb::SBAddress brkPtAddr = brkPtLoc.GetAddress(); + lldb::SBSymbolContext symbolCntxt = brkPtAddr.GetSymbolContext(lldb::eSymbolContextEverything); + const MIchar *pUnkwn = "??"; + lldb::SBModule rModule = symbolCntxt.GetModule(); + const MIchar *pModule = rModule.IsValid() ? rModule.GetFileSpec().GetFilename() : pUnkwn; + MIunused(pModule); + const MIchar *pFile = pUnkwn; + const MIchar *pFn = pUnkwn; + const MIchar *pFilePath = pUnkwn; + size_t nLine = 0; + const size_t nAddr = brkPtAddr.GetLoadAddress(m_lldbTarget); + + lldb::SBCompileUnit rCmplUnit = symbolCntxt.GetCompileUnit(); + if (rCmplUnit.IsValid()) + { + lldb::SBFileSpec rFileSpec = rCmplUnit.GetFileSpec(); + pFile = rFileSpec.GetFilename(); + pFilePath = rFileSpec.GetDirectory(); + lldb::SBFunction rFn = symbolCntxt.GetFunction(); + if (rFn.IsValid()) + pFn = rFn.GetName(); + lldb::SBLineEntry rLnEntry = symbolCntxt.GetLineEntry(); + if (rLnEntry.GetLine() > 0) + nLine = rLnEntry.GetLine(); + } + + vrwBrkPtInfo.m_id = vBrkPt.GetID(); + vrwBrkPtInfo.m_strType = "breakpoint"; + vrwBrkPtInfo.m_pc = nAddr; + vrwBrkPtInfo.m_fnName = pFn; + vrwBrkPtInfo.m_fileName = pFile; + vrwBrkPtInfo.m_path = pFilePath; + vrwBrkPtInfo.m_nLine = nLine; + vrwBrkPtInfo.m_nTimes = vBrkPt.GetHitCount(); + + return MIstatus::success; } diff --git a/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h b/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h index ca7ea27f5611..e2463f1c89ca 100644 --- a/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h +++ b/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLLDBDebugSessionInfo.h +// File: MICmnLLDBDebugSessionInfo.h // -// Overview: CMICmnLLDBDebugSessionInfo interface. +// Overview: CMICmnLLDBDebugSessionInfo interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include @@ -43,194 +43,211 @@ class CMICmnMIValueTuple; class CMICmnMIValueList; //++ ============================================================================ -// Details: MI debug session object that holds debugging information between -// instances of MI commands executing their work and producing MI -// result records. Information/data is set by one or many commands then -// retrieved by the same or other sebsequent commands. -// It primarily to hold LLDB type objects. -// A singleton class. -// Gotchas: None. -// Authors: Illya Rudkin 04/03/2014. -// Changes: None. +// Details: MI debug session object that holds debugging information between +// instances of MI commands executing their work and producing MI +// result records. Information/data is set by one or many commands then +// retrieved by the same or other sebsequent commands. +// It primarily to hold LLDB type objects. +// A singleton class. +// Gotchas: None. +// Authors: Illya Rudkin 04/03/2014. +// Changes: None. //-- -class CMICmnLLDBDebugSessionInfo -: public CMICmnBase -, public MI::ISingleton< CMICmnLLDBDebugSessionInfo > +class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton { - friend class MI::ISingleton< CMICmnLLDBDebugSessionInfo >; - -// Structs: -public: - //++ ============================================================================ - // Details: Break point information object. Used to easily pass information about - // a break around and record break point information to be recalled by - // other commands or LLDB event handling functions. - //-- - struct SBrkPtInfo - { - SBrkPtInfo( void ) - : m_id( 0 ) - , m_bDisp( false ) - , m_bEnabled( false ) - , m_pc( 0 ) - , m_nLine( 0 ) - , m_bHaveArgOptionThreadGrp( false ) - , m_nTimes( 0 ) - , m_bPending( false ) - , m_nIgnore( 0 ) - , m_bCondition( false ) - , m_bBrkPtThreadId( false ) - , m_nBrkPtThreadId( 0 ) - { - } - - MIuint m_id; // LLDB break point ID. - CMIUtilString m_strType; // Break point type. - bool m_bDisp ; // True = "del", false = "keep". - bool m_bEnabled; // True = enabled, false = disabled break point. - MIuint m_pc; // Address number. - CMIUtilString m_fnName; // Function name. - CMIUtilString m_fileName; // File name text. - CMIUtilString m_path; // Full file name and path text. - MIuint m_nLine; // File line number. - bool m_bHaveArgOptionThreadGrp; // True = include MI field, false = do not include "thread-groups". - CMIUtilString m_strOptThrdGrp; // Thread group number. - MIuint m_nTimes; // The count of the breakpoint existence. - CMIUtilString m_strOrigLoc; // The name of the break point. - bool m_bPending; // True = the breakpoint has not been established yet, false = location found - MIuint m_nIgnore; // The number of time the breakpoint is run over before it is stopped on a hit - bool m_bCondition; // True = break point is conditional, use condition expression, false = no condition - CMIUtilString m_strCondition; // Break point condition expression - bool m_bBrkPtThreadId; // True = break point is specified to work with a specific thread, false = no specified thread given - MIuint m_nBrkPtThreadId; // Restrict the breakpoint to the specified thread-id - }; - -// Typedefs: -public: - typedef std::vector< uint32_t > VecActiveThreadId_t; - -// Methods: -public: - bool Initialize( void ); - bool Shutdown( void ); - - // Variant type data which can be assigned and retrieved across all command instances - template< typename T > - bool SharedDataAdd( const CMIUtilString & vKey, const T & vData ); - template< typename T > - bool SharedDataRetrieve( const CMIUtilString & vKey, T & vwData ); - bool SharedDataDestroy( void ); - - // Common command required functionality - bool AccessPath( const CMIUtilString & vPath, bool & vwbYesAccessible ); - bool GetFrameInfo( const lldb::SBFrame & vrFrame, lldb::addr_t & vwPc, CMIUtilString & vwFnName, CMIUtilString & vwFileName, CMIUtilString & vwPath, MIuint & vwnLine ); - bool GetThreadFrames( const SMICmdData & vCmdData, const MIuint vThreadIdx, CMIUtilString & vwrThreadFrames ); - bool GetThreadFrames2( const SMICmdData & vCmdData, const MIuint vThreadIdx, CMIUtilString & vwrThreadFrames ); - bool ResolvePath( const SMICmdData & vCmdData, const CMIUtilString & vPath, CMIUtilString & vwrResolvedPath ); - bool ResolvePath( const CMIUtilString & vstrUnknown, CMIUtilString & vwrResolvedPath ); - bool MIResponseFormFrameInfo( const lldb::SBThread & vrThread, const MIuint vnLevel, CMICmnMIValueTuple & vwrMiValueTuple ); - bool MIResponseFormFrameInfo( const lldb::addr_t vPc, const CMIUtilString & vFnName, const CMIUtilString & vFileName, const CMIUtilString & vPath, const MIuint vnLine, CMICmnMIValueTuple & vwrMiValueTuple ); - bool MIResponseFormFrameInfo2( const lldb::addr_t vPc, const CMIUtilString & vArgInfo, const CMIUtilString & vFnName, const CMIUtilString & vFileName, const CMIUtilString & vPath, const MIuint vnLine, CMICmnMIValueTuple & vwrMiValueTuple ); - bool MIResponseFormThreadInfo( const SMICmdData & vCmdData, const lldb::SBThread & vrThread, CMICmnMIValueTuple & vwrMIValueTuple ); - bool MIResponseFormThreadInfo2( const SMICmdData & vCmdData, const lldb::SBThread & vrThread, CMICmnMIValueTuple & vwrMIValueTuple ); - bool MIResponseFormThreadInfo3( const SMICmdData & vCmdData, const lldb::SBThread & vrThread, CMICmnMIValueTuple & vwrMIValueTuple ); - bool MIResponseFormVariableInfo( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList ); - bool MIResponseFormVariableInfo2( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList ); - bool MIResponseFormVariableInfo3( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList ); - bool MIResponseFormBrkPtFrameInfo( const SBrkPtInfo & vrBrkPtInfo, CMICmnMIValueTuple & vwrMiValueTuple ); - bool MIResponseFormBrkPtInfo( const SBrkPtInfo & vrBrkPtInfo, CMICmnMIValueTuple & vwrMiValueTuple ); - bool GetBrkPtInfo( const lldb::SBBreakpoint & vBrkPt, SBrkPtInfo & vrwBrkPtInfo ) const; - bool RecordBrkPtInfo( const MIuint vnBrkPtId, const SBrkPtInfo & vrBrkPtInfo ); - bool RecordBrkPtInfoGet( const MIuint vnBrkPtId, SBrkPtInfo & vrwBrkPtInfo ) const; - bool RecordBrkPtInfoDelete( const MIuint vnBrkPtId ); - -// Attributes: -public: - // The following are available to all command instances - lldb::SBDebugger & m_rLldbDebugger; - lldb::SBListener & m_rLlldbListener; - lldb::SBTarget m_lldbTarget; - lldb::SBProcess m_lldbProcess; - const MIuint m_nBrkPointCntMax; - VecActiveThreadId_t m_vecActiveThreadId; - lldb::tid_t m_currentSelectedThread; - - // These are keys that can be used to access the shared data map - // Note: This list is expected to grow and will be moved and abstracted in the future. - const CMIUtilString m_constStrSharedDataKeyWkDir; + friend class MI::ISingleton; + + // Structs: + public: + //++ ============================================================================ + // Details: Break point information object. Used to easily pass information about + // a break around and record break point information to be recalled by + // other commands or LLDB event handling functions. + //-- + struct SBrkPtInfo + { + SBrkPtInfo(void) + : m_id(0) + , m_bDisp(false) + , m_bEnabled(false) + , m_pc(0) + , m_nLine(0) + , m_bHaveArgOptionThreadGrp(false) + , m_nTimes(0) + , m_bPending(false) + , m_nIgnore(0) + , m_bCondition(false) + , m_bBrkPtThreadId(false) + , m_nBrkPtThreadId(0) + { + } + + MIuint m_id; // LLDB break point ID. + CMIUtilString m_strType; // Break point type. + bool m_bDisp; // True = "del", false = "keep". + bool m_bEnabled; // True = enabled, false = disabled break point. + MIuint m_pc; // Address number. + CMIUtilString m_fnName; // Function name. + CMIUtilString m_fileName; // File name text. + CMIUtilString m_path; // Full file name and path text. + MIuint m_nLine; // File line number. + bool m_bHaveArgOptionThreadGrp; // True = include MI field, false = do not include "thread-groups". + CMIUtilString m_strOptThrdGrp; // Thread group number. + MIuint m_nTimes; // The count of the breakpoint existence. + CMIUtilString m_strOrigLoc; // The name of the break point. + bool m_bPending; // True = the breakpoint has not been established yet, false = location found + MIuint m_nIgnore; // The number of time the breakpoint is run over before it is stopped on a hit + bool m_bCondition; // True = break point is conditional, use condition expression, false = no condition + CMIUtilString m_strCondition; // Break point condition expression + bool m_bBrkPtThreadId; // True = break point is specified to work with a specific thread, false = no specified thread given + MIuint m_nBrkPtThreadId; // Restrict the breakpoint to the specified thread-id + }; + + // Enumerations: + public: + //++ =================================================================== + // Details: The type of variable used by MIResponseFormVariableInfo family functions. + //-- + enum VariableType_e + { + eVariableType_InScope = (1u << 0), // In scope only. + eVariableType_Statics = (1u << 1), // Statics. + eVariableType_Locals = (1u << 2), // Locals. + eVariableType_Arguments = (1u << 3) // Arguments. + }; + + // Typedefs: + public: + typedef std::vector VecActiveThreadId_t; + + // Methods: + public: + bool Initialize(void); + bool Shutdown(void); + + // Variant type data which can be assigned and retrieved across all command instances + template bool SharedDataAdd(const CMIUtilString &vKey, const T &vData); + template bool SharedDataRetrieve(const CMIUtilString &vKey, T &vwData); + bool SharedDataDestroy(void); + + // Common command required functionality + bool AccessPath(const CMIUtilString &vPath, bool &vwbYesAccessible); + bool GetFrameInfo(const lldb::SBFrame &vrFrame, lldb::addr_t &vwPc, CMIUtilString &vwFnName, CMIUtilString &vwFileName, + CMIUtilString &vwPath, MIuint &vwnLine); + bool GetThreadFrames(const SMICmdData &vCmdData, const MIuint vThreadIdx, CMIUtilString &vwrThreadFrames); + bool GetThreadFrames2(const SMICmdData &vCmdData, const MIuint vThreadIdx, CMIUtilString &vwrThreadFrames); + bool ResolvePath(const SMICmdData &vCmdData, const CMIUtilString &vPath, CMIUtilString &vwrResolvedPath); + bool ResolvePath(const CMIUtilString &vstrUnknown, CMIUtilString &vwrResolvedPath); + bool MIResponseFormFrameInfo(const lldb::SBThread &vrThread, const MIuint vnLevel, CMICmnMIValueTuple &vwrMiValueTuple); + bool MIResponseFormFrameInfo(const lldb::addr_t vPc, const CMIUtilString &vFnName, const CMIUtilString &vFileName, + const CMIUtilString &vPath, const MIuint vnLine, CMICmnMIValueTuple &vwrMiValueTuple); + bool MIResponseFormFrameInfo2(const lldb::addr_t vPc, const CMIUtilString &vArgInfo, const CMIUtilString &vFnName, + const CMIUtilString &vFileName, const CMIUtilString &vPath, const MIuint vnLine, + CMICmnMIValueTuple &vwrMiValueTuple); + bool MIResponseFormThreadInfo(const SMICmdData &vCmdData, const lldb::SBThread &vrThread, CMICmnMIValueTuple &vwrMIValueTuple); + bool MIResponseFormThreadInfo2(const SMICmdData &vCmdData, const lldb::SBThread &vrThread, CMICmnMIValueTuple &vwrMIValueTuple); + bool MIResponseFormThreadInfo3(const SMICmdData &vCmdData, const lldb::SBThread &vrThread, CMICmnMIValueTuple &vwrMIValueTuple); + bool MIResponseFormVariableInfo(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList &vwrMiValueList); + bool MIResponseFormVariableInfo2(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList &vwrMiValueList); + bool MIResponseFormVariableInfo3(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList &vwrMiValueList); + bool MIResponseFormBrkPtFrameInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple); + bool MIResponseFormBrkPtInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple); + bool GetBrkPtInfo(const lldb::SBBreakpoint &vBrkPt, SBrkPtInfo &vrwBrkPtInfo) const; + bool RecordBrkPtInfo(const MIuint vnBrkPtId, const SBrkPtInfo &vrBrkPtInfo); + bool RecordBrkPtInfoGet(const MIuint vnBrkPtId, SBrkPtInfo &vrwBrkPtInfo) const; + bool RecordBrkPtInfoDelete(const MIuint vnBrkPtId); + + // Attributes: + public: + // The following are available to all command instances + lldb::SBDebugger &m_rLldbDebugger; + lldb::SBListener &m_rLlldbListener; + lldb::SBTarget m_lldbTarget; + lldb::SBProcess m_lldbProcess; + const MIuint m_nBrkPointCntMax; + VecActiveThreadId_t m_vecActiveThreadId; + lldb::tid_t m_currentSelectedThread; + + // These are keys that can be used to access the shared data map + // Note: This list is expected to grow and will be moved and abstracted in the future. + const CMIUtilString m_constStrSharedDataKeyWkDir; const CMIUtilString m_constStrSharedDataSolibPath; -// Typedefs: -private: - typedef std::vector< CMICmnLLDBDebugSessionInfoVarObj > VecVarObj_t; - typedef std::map< MIuint, SBrkPtInfo > MapBrkPtIdToBrkPtInfo_t; - typedef std::pair< MIuint, SBrkPtInfo > MapPairBrkPtIdToBrkPtInfo_t; - -// Methods: -private: - /* ctor */ CMICmnLLDBDebugSessionInfo( void ); - /* ctor */ CMICmnLLDBDebugSessionInfo( const CMICmnLLDBDebugSessionInfo & ); - void operator=( const CMICmnLLDBDebugSessionInfo & ); - // - bool GetVariableInfo( const MIuint vnMaxDepth, const lldb::SBValue & vrValue, const bool vbIsChildValue, CMICmnMIValueList & vwrMiValueList, MIuint & vrwnDepth ); - bool GetVariableInfo2( const MIuint vnMaxDepth, const lldb::SBValue & vrValue, const bool vbIsChildValue, CMICmnMIValueList & vwrMiValueList, MIuint & vrwnDepth ); - -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMICmnLLDBDebugSessionInfo( void ); - -// Attributes: -private: - CMIUtilMapIdToVariant m_mapIdToSessionData; // Hold and retrieve key to value data available across all commands - VecVarObj_t m_vecVarObj; // Vector of session variable objects - MapBrkPtIdToBrkPtInfo_t m_mapBrkPtIdToBrkPtInfo; + // Typedefs: + private: + typedef std::vector VecVarObj_t; + typedef std::map MapBrkPtIdToBrkPtInfo_t; + typedef std::pair MapPairBrkPtIdToBrkPtInfo_t; + + // Methods: + private: + /* ctor */ CMICmnLLDBDebugSessionInfo(void); + /* ctor */ CMICmnLLDBDebugSessionInfo(const CMICmnLLDBDebugSessionInfo &); + void operator=(const CMICmnLLDBDebugSessionInfo &); + // + bool GetVariableInfo(const MIuint vnMaxDepth, const lldb::SBValue &vrValue, const bool vbIsChildValue, + CMICmnMIValueList &vwrMiValueList, MIuint &vrwnDepth); + bool GetVariableInfo2(const MIuint vnMaxDepth, const lldb::SBValue &vrValue, const bool vbIsChildValue, + CMICmnMIValueList &vwrMiValueList, MIuint &vrwnDepth); + + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMICmnLLDBDebugSessionInfo(void); + + // Attributes: + private: + CMIUtilMapIdToVariant m_mapIdToSessionData; // Hold and retrieve key to value data available across all commands + VecVarObj_t m_vecVarObj; // Vector of session variable objects + MapBrkPtIdToBrkPtInfo_t m_mapBrkPtIdToBrkPtInfo; }; //++ ------------------------------------------------------------------------------------ -// Details: Command instances can create and share data between other instances of commands. -// This function adds new data to the shared data. Using the same ID more than -// once replaces any previous matching data keys. -// Type: Template method. -// Args: T - The type of the object to be stored. -// vKey - (R) A non empty unique data key to retrieve the data by. -// vData - (R) Data to be added to the share. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Command instances can create and share data between other instances of commands. +// This function adds new data to the shared data. Using the same ID more than +// once replaces any previous matching data keys. +// Type: Template method. +// Args: T - The type of the object to be stored. +// vKey - (R) A non empty unique data key to retrieve the data by. +// vData - (R) Data to be added to the share. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -template< typename T > -bool CMICmnLLDBDebugSessionInfo::SharedDataAdd( const CMIUtilString & vKey, const T & vData ) +template +bool +CMICmnLLDBDebugSessionInfo::SharedDataAdd(const CMIUtilString &vKey, const T &vData) { - if( !m_mapIdToSessionData.Add< T >( vKey, vData ) ) - { - SetErrorDescription( m_mapIdToSessionData.GetErrorDescription() ); - return MIstatus::failure; - } + if (!m_mapIdToSessionData.Add(vKey, vData)) + { + SetErrorDescription(m_mapIdToSessionData.GetErrorDescription()); + return MIstatus::failure; + } - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Command instances can create and share data between other instances of commands. -// This function retrieves data from the shared data container. -// Type: Method. -// Args: T - The type of the object being retrieved. -// vKey - (R) A non empty unique data key to retrieve the data by. -// vData - (W) The data. -// Return: bool - True = data found, false = data not found or an error occurred trying to fetch. -// Throws: None. +// Details: Command instances can create and share data between other instances of commands. +// This function retrieves data from the shared data container. +// Type: Method. +// Args: T - The type of the object being retrieved. +// vKey - (R) A non empty unique data key to retrieve the data by. +// vData - (W) The data. +// Return: bool - True = data found, false = data not found or an error occurred trying to fetch. +// Throws: None. //-- -template< typename T > -bool CMICmnLLDBDebugSessionInfo::SharedDataRetrieve( const CMIUtilString & vKey, T & vwData ) +template +bool +CMICmnLLDBDebugSessionInfo::SharedDataRetrieve(const CMIUtilString &vKey, T &vwData) { - bool bDataFound = false; + bool bDataFound = false; - if( !m_mapIdToSessionData.Get< T >( vKey, vwData, bDataFound ) ) - { - SetErrorDescription( m_mapIdToSessionData.GetErrorDescription() ); - return MIstatus::failure; - } + if (!m_mapIdToSessionData.Get(vKey, vwData, bDataFound)) + { + SetErrorDescription(m_mapIdToSessionData.GetErrorDescription()); + return MIstatus::failure; + } - return bDataFound; -} \ No newline at end of file + return bDataFound; +} diff --git a/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp b/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp index d519875993fe..c9abdd1cf90c 100644 --- a/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp +++ b/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLLDBDebugSessionInfoVarObj.cpp +// File: MICmnLLDBDebugSessionInfoVarObj.cpp // -// Overview: CMICmnLLDBDebugSessionInfoVarObj implementation. +// Overview: CMICmnLLDBDebugSessionInfoVarObj implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -25,546 +25,557 @@ #include "MICmnLLDBUtilSBValue.h" // Instantiations: -const MIchar * CMICmnLLDBDebugSessionInfoVarObj::ms_aVarFormatStrings[] = -{ - // CODETAG_SESSIONINFO_VARFORMAT_ENUM - // *** Order is import here. - "", - "binary", - "octal", - "decimal", - "hexadecimal", - "natural" -}; -const MIchar * CMICmnLLDBDebugSessionInfoVarObj::ms_aVarFormatChars[] = -{ - // CODETAG_SESSIONINFO_VARFORMAT_ENUM - // *** Order is import here. - "", - "t", - "o", - "d", - "x", - "N" -}; -CMICmnLLDBDebugSessionInfoVarObj::MapKeyToVarObj_t CMICmnLLDBDebugSessionInfoVarObj::ms_mapVarIdToVarObj; -MIuint CMICmnLLDBDebugSessionInfoVarObj::ms_nVarUniqueId = 0; // Index from 0 +const MIchar *CMICmnLLDBDebugSessionInfoVarObj::ms_aVarFormatStrings[] = { + // CODETAG_SESSIONINFO_VARFORMAT_ENUM + // *** Order is import here. + "", "binary", "octal", "decimal", "hexadecimal", "natural"}; +const MIchar *CMICmnLLDBDebugSessionInfoVarObj::ms_aVarFormatChars[] = { + // CODETAG_SESSIONINFO_VARFORMAT_ENUM + // *** Order is import here. + "", "t", "o", "d", "x", "N"}; +CMICmnLLDBDebugSessionInfoVarObj::MapKeyToVarObj_t CMICmnLLDBDebugSessionInfoVarObj::ms_mapVarIdToVarObj; +MIuint CMICmnLLDBDebugSessionInfoVarObj::ms_nVarUniqueId = 0; // Index from 0 //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBDebugSessionInfoVarObj constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. -//-- -CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( void ) -: m_eVarFormat( eVarFormat_Natural ) -, m_eVarType( eVarType_Internal ) +// Details: CMICmnLLDBDebugSessionInfoVarObj constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. +//-- +CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj(void) + : m_eVarFormat(eVarFormat_Natural) + , m_eVarType(eVarType_Internal) { - // Do not call UpdateValue() in here as not necessary + // Do not call UpdateValue() in here as not necessary } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBDebugSessionInfoVarObj constructor. -// Type: Method. -// Args: vrStrNameReal - (R) The actual name of the variable, the expression. -// vrStrName - (R) The name given for *this var object. -// vrValue - (R) The LLDB SBValue object represented by *this object. -// Return: None. -// Throws: None. -//-- -CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( const CMIUtilString & vrStrNameReal, const CMIUtilString & vrStrName, const lldb::SBValue & vrValue ) -: m_eVarFormat( eVarFormat_Natural ) -, m_eVarType( eVarType_Internal ) -, m_strName( vrStrName ) -, m_SBValue( vrValue ) -, m_strNameReal( vrStrNameReal ) -{ - UpdateValue(); +// Details: CMICmnLLDBDebugSessionInfoVarObj constructor. +// Type: Method. +// Args: vrStrNameReal - (R) The actual name of the variable, the expression. +// vrStrName - (R) The name given for *this var object. +// vrValue - (R) The LLDB SBValue object represented by *this object. +// Return: None. +// Throws: None. +//-- +CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj(const CMIUtilString &vrStrNameReal, const CMIUtilString &vrStrName, + const lldb::SBValue &vrValue) + : m_eVarFormat(eVarFormat_Natural) + , m_eVarType(eVarType_Internal) + , m_strName(vrStrName) + , m_SBValue(vrValue) + , m_strNameReal(vrStrNameReal) +{ + UpdateValue(); } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBDebugSessionInfoVarObj constructor. -// Type: Method. -// Args: vrStrNameReal - (R) The actual name of the variable, the expression. -// vrStrName - (R) The name given for *this var object. -// vrValue - (R) The LLDB SBValue object represented by *this object. -// vrStrVarObjParentName - (R) The var object parent to *this var object (LLDB SBValue equivalent). -// Return: None. -// Throws: None. -//-- -CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( const CMIUtilString & vrStrNameReal, const CMIUtilString & vrStrName, const lldb::SBValue & vrValue, const CMIUtilString & vrStrVarObjParentName ) -: m_eVarFormat( eVarFormat_Natural ) -, m_eVarType( eVarType_Internal ) -, m_strName( vrStrName ) -, m_SBValue( vrValue ) -, m_strNameReal( vrStrNameReal ) -, m_strVarObjParentName( vrStrVarObjParentName ) -{ - UpdateValue(); +// Details: CMICmnLLDBDebugSessionInfoVarObj constructor. +// Type: Method. +// Args: vrStrNameReal - (R) The actual name of the variable, the expression. +// vrStrName - (R) The name given for *this var object. +// vrValue - (R) The LLDB SBValue object represented by *this object. +// vrStrVarObjParentName - (R) The var object parent to *this var object (LLDB SBValue equivalent). +// Return: None. +// Throws: None. +//-- +CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj(const CMIUtilString &vrStrNameReal, const CMIUtilString &vrStrName, + const lldb::SBValue &vrValue, const CMIUtilString &vrStrVarObjParentName) + : m_eVarFormat(eVarFormat_Natural) + , m_eVarType(eVarType_Internal) + , m_strName(vrStrName) + , m_SBValue(vrValue) + , m_strNameReal(vrStrNameReal) + , m_strVarObjParentName(vrStrVarObjParentName) +{ + UpdateValue(); } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBDebugSessionInfoVarObj copy constructor. -// Type: Method. -// Args: vrOther - (R) The object to copy from. -// Return: None. -// Throws: None. +// Details: CMICmnLLDBDebugSessionInfoVarObj copy constructor. +// Type: Method. +// Args: vrOther - (R) The object to copy from. +// Return: None. +// Throws: None. //-- -CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( const CMICmnLLDBDebugSessionInfoVarObj & vrOther ) +CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj(const CMICmnLLDBDebugSessionInfoVarObj &vrOther) { - CopyOther( vrOther ); + CopyOther(vrOther); } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBDebugSessionInfoVarObj copy constructor. -// Type: Method. -// Args: vrOther - (R) The object to copy from. -// Return: None. -// Throws: None. +// Details: CMICmnLLDBDebugSessionInfoVarObj copy constructor. +// Type: Method. +// Args: vrOther - (R) The object to copy from. +// Return: None. +// Throws: None. //-- -CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( CMICmnLLDBDebugSessionInfoVarObj & vrOther ) +CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj(CMICmnLLDBDebugSessionInfoVarObj &vrOther) { - CopyOther( vrOther ); + CopyOther(vrOther); } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBDebugSessionInfoVarObj move constructor. -// Type: Method. -// Args: vrwOther - (R) The object to copy from. -// Return: None. -// Throws: None. +// Details: CMICmnLLDBDebugSessionInfoVarObj move constructor. +// Type: Method. +// Args: vrwOther - (R) The object to copy from. +// Return: None. +// Throws: None. //-- -CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( CMICmnLLDBDebugSessionInfoVarObj && vrwOther ) +CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj(CMICmnLLDBDebugSessionInfoVarObj &&vrwOther) { - MoveOther( vrwOther ); + MoveOther(vrwOther); } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBDebugSessionInfoVarObj assignment operator. -// Type: Method. -// Args: vrOther - (R) The object to copy from. -// Return: CMICmnLLDBDebugSessionInfoVarObj & - Updated *this object. -// Throws: None. +// Details: CMICmnLLDBDebugSessionInfoVarObj assignment operator. +// Type: Method. +// Args: vrOther - (R) The object to copy from. +// Return: CMICmnLLDBDebugSessionInfoVarObj & - Updated *this object. +// Throws: None. //-- -CMICmnLLDBDebugSessionInfoVarObj & CMICmnLLDBDebugSessionInfoVarObj::operator= ( const CMICmnLLDBDebugSessionInfoVarObj & vrOther ) +CMICmnLLDBDebugSessionInfoVarObj &CMICmnLLDBDebugSessionInfoVarObj::operator=(const CMICmnLLDBDebugSessionInfoVarObj &vrOther) { - CopyOther( vrOther ); + CopyOther(vrOther); - return *this; + return *this; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBDebugSessionInfoVarObj assignment operator. -// Type: Method. -// Args: vrwOther - (R) The object to copy from. -// Return: CMICmnLLDBDebugSessionInfoVarObj & - Updated *this object. -// Throws: None. +// Details: CMICmnLLDBDebugSessionInfoVarObj assignment operator. +// Type: Method. +// Args: vrwOther - (R) The object to copy from. +// Return: CMICmnLLDBDebugSessionInfoVarObj & - Updated *this object. +// Throws: None. //-- -CMICmnLLDBDebugSessionInfoVarObj & CMICmnLLDBDebugSessionInfoVarObj::operator= ( CMICmnLLDBDebugSessionInfoVarObj && vrwOther ) +CMICmnLLDBDebugSessionInfoVarObj &CMICmnLLDBDebugSessionInfoVarObj::operator=(CMICmnLLDBDebugSessionInfoVarObj &&vrwOther) { - MoveOther( vrwOther ); + MoveOther(vrwOther); - return *this; + return *this; } //++ ------------------------------------------------------------------------------------ -// Details: Copy the other instance of that object to *this object. -// Type: Method. -// Args: vrOther - (R) The object to copy from. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugSessionInfoVarObj::CopyOther( const CMICmnLLDBDebugSessionInfoVarObj & vrOther ) -{ - // Check for self-assignment - if( this == &vrOther ) - return MIstatus::success; - - m_eVarFormat = vrOther.m_eVarFormat; - m_eVarType = vrOther.m_eVarType; - m_strName = vrOther.m_strName; - m_SBValue = vrOther.m_SBValue; - m_strNameReal = vrOther.m_strNameReal; - m_strFormattedValue = vrOther.m_strFormattedValue; - m_strVarObjParentName = vrOther.m_strVarObjParentName; - - return MIstatus::success; +// Details: Copy the other instance of that object to *this object. +// Type: Method. +// Args: vrOther - (R) The object to copy from. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. +//-- +bool +CMICmnLLDBDebugSessionInfoVarObj::CopyOther(const CMICmnLLDBDebugSessionInfoVarObj &vrOther) +{ + // Check for self-assignment + if (this == &vrOther) + return MIstatus::success; + + m_eVarFormat = vrOther.m_eVarFormat; + m_eVarType = vrOther.m_eVarType; + m_strName = vrOther.m_strName; + m_SBValue = vrOther.m_SBValue; + m_strNameReal = vrOther.m_strNameReal; + m_strFormattedValue = vrOther.m_strFormattedValue; + m_strVarObjParentName = vrOther.m_strVarObjParentName; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Move that object to *this object. -// Type: Method. -// Args: vrwOther - (RW) The object to copy from. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugSessionInfoVarObj::MoveOther( CMICmnLLDBDebugSessionInfoVarObj & vrwOther ) -{ - // Check for self-assignment - if( this == &vrwOther ) - return MIstatus::success; - - CopyOther( vrwOther ); - vrwOther.m_eVarFormat = eVarFormat_Natural; - vrwOther.m_eVarType = eVarType_Internal; - vrwOther.m_strName.clear(); - vrwOther.m_SBValue.Clear(); - vrwOther.m_strNameReal.clear(); - vrwOther.m_strFormattedValue.clear(); - vrwOther.m_strVarObjParentName.clear(); - - return MIstatus::success; +// Details: Move that object to *this object. +// Type: Method. +// Args: vrwOther - (RW) The object to copy from. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. +//-- +bool +CMICmnLLDBDebugSessionInfoVarObj::MoveOther(CMICmnLLDBDebugSessionInfoVarObj &vrwOther) +{ + // Check for self-assignment + if (this == &vrwOther) + return MIstatus::success; + + CopyOther(vrwOther); + vrwOther.m_eVarFormat = eVarFormat_Natural; + vrwOther.m_eVarType = eVarType_Internal; + vrwOther.m_strName.clear(); + vrwOther.m_SBValue.Clear(); + vrwOther.m_strNameReal.clear(); + vrwOther.m_strFormattedValue.clear(); + vrwOther.m_strVarObjParentName.clear(); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBDebugSessionInfoVarObj destructor. -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnLLDBDebugSessionInfoVarObj destructor. +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnLLDBDebugSessionInfoVarObj::~CMICmnLLDBDebugSessionInfoVarObj( void ) +CMICmnLLDBDebugSessionInfoVarObj::~CMICmnLLDBDebugSessionInfoVarObj(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the var format enumeration for the specified string. -// Type: Static method. -// Args: vrStrFormat - (R) Text description of the var format. -// Return: varFormat_e - Var format enumeration. -// - No match found return eVarFormat_Invalid. -// Throws: None. -//-- -CMICmnLLDBDebugSessionInfoVarObj::varFormat_e CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForString( const CMIUtilString & vrStrFormat ) -{ - // CODETAG_SESSIONINFO_VARFORMAT_ENUM - for( MIuint i = 0; i < eVarFormat_count; i++ ) - { - const MIchar * pVarFormatString = ms_aVarFormatStrings[ i ]; - if( vrStrFormat == pVarFormatString ) - return static_cast< varFormat_e >( i ); - } - - return eVarFormat_Invalid; +// Details: Retrieve the var format enumeration for the specified string. +// Type: Static method. +// Args: vrStrFormat - (R) Text description of the var format. +// Return: varFormat_e - Var format enumeration. +// - No match found return eVarFormat_Invalid. +// Throws: None. +//-- +CMICmnLLDBDebugSessionInfoVarObj::varFormat_e +CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForString(const CMIUtilString &vrStrFormat) +{ + // CODETAG_SESSIONINFO_VARFORMAT_ENUM + for (MIuint i = 0; i < eVarFormat_count; i++) + { + const MIchar *pVarFormatString = ms_aVarFormatStrings[i]; + if (vrStrFormat == pVarFormatString) + return static_cast(i); + } + + return eVarFormat_Invalid; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the var format enumeration for the specified character. -// Type: Static method. -// Args: vrcFormat - (R) Character representing the var format. -// Return: varFormat_e - Var format enumeration. -// - No match found return eVarFormat_Invalid. -// Throws: None. -//-- -CMICmnLLDBDebugSessionInfoVarObj::varFormat_e CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar( const MIchar & vrcFormat ) -{ - if( 'r' == vrcFormat ) - return eVarFormat_Hex; - - // CODETAG_SESSIONINFO_VARFORMAT_ENUM - for( MIuint i = 0; i < eVarFormat_count; i++ ) - { - const MIchar * pVarFormatChar = ms_aVarFormatChars[ i ]; - if( *pVarFormatChar == vrcFormat ) - return static_cast< varFormat_e >( i ); - } - - return eVarFormat_Invalid; +// Details: Retrieve the var format enumeration for the specified character. +// Type: Static method. +// Args: vrcFormat - (R) Character representing the var format. +// Return: varFormat_e - Var format enumeration. +// - No match found return eVarFormat_Invalid. +// Throws: None. +//-- +CMICmnLLDBDebugSessionInfoVarObj::varFormat_e +CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(const MIchar &vrcFormat) +{ + if ('r' == vrcFormat) + return eVarFormat_Hex; + + // CODETAG_SESSIONINFO_VARFORMAT_ENUM + for (MIuint i = 0; i < eVarFormat_count; i++) + { + const MIchar *pVarFormatChar = ms_aVarFormatChars[i]; + if (*pVarFormatChar == vrcFormat) + return static_cast(i); + } + + return eVarFormat_Invalid; } //++ ------------------------------------------------------------------------------------ -// Details: Return the equivalent var value formatted string for the given value type. -// The SBValue vrValue parameter is checked by LLDB private code for valid -// scalar type via MI Driver proxy function as the valued returned can also be -// an error condition. The proxy function determines if the check was valid -// otherwise return an error condition state by other means saying so. -// Type: Static method. -// Args: vrValue - (R) The var value object. -// veVarFormat - (R) Var format enumeration. -// Returns: CMIUtilString - Value formatted string. -// Throws: None. -//-- -CMIUtilString CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted( const lldb::SBValue & vrValue, const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat ) -{ - CMIUtilString strFormattedValue; - - MIuint64 nValue = 0; - if( CMICmnLLDBProxySBValue::GetValueAsUnsigned( vrValue, nValue ) == MIstatus::success ) - { - lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValue ); - strFormattedValue = GetStringFormatted( nValue, rValue.GetValue(), veVarFormat ); - } - else - { - // Composite variable type i.e. struct - strFormattedValue = "{...}"; - } - - return strFormattedValue; +// Details: Return the equivalent var value formatted string for the given value type. +// The SBValue vrValue parameter is checked by LLDB private code for valid +// scalar type via MI Driver proxy function as the valued returned can also be +// an error condition. The proxy function determines if the check was valid +// otherwise return an error condition state by other means saying so. +// Type: Static method. +// Args: vrValue - (R) The var value object. +// veVarFormat - (R) Var format enumeration. +// Returns: CMIUtilString - Value formatted string. +// Throws: None. +//-- +CMIUtilString +CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(const lldb::SBValue &vrValue, + const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat) +{ + CMIUtilString strFormattedValue; + + MIuint64 nValue = 0; + if (CMICmnLLDBProxySBValue::GetValueAsUnsigned(vrValue, nValue) == MIstatus::success) + { + lldb::SBValue &rValue = const_cast(vrValue); + strFormattedValue = GetStringFormatted(nValue, rValue.GetValue(), veVarFormat); + } + else + { + // Composite variable type i.e. struct + strFormattedValue = "{...}"; + } + + return strFormattedValue; } //++ ------------------------------------------------------------------------------------ -// Details: Return nuber formatted string according to the given value type. -// Type: Static method. -// Args: vnValue - (R) The number value to get formatted. -// vpStrValueNatural - (R) The natural representation of the number value. -// veVarFormat - (R) Var format enumeration. -// Returns: CMIUtilString - Numerical formatted string. -// Throws: None. -//-- -CMIUtilString CMICmnLLDBDebugSessionInfoVarObj::GetStringFormatted( const MIuint64 vnValue, const MIchar * vpStrValueNatural, const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat ) -{ - CMIUtilString strFormattedValue; - - switch( veVarFormat ) - { - case eVarFormat_Binary: - strFormattedValue = CMIUtilString::FormatBinary( vnValue ); - break; - case eVarFormat_Octal: - strFormattedValue = CMIUtilString::Format( "0%llo", vnValue ); - break; - case eVarFormat_Decimal: - strFormattedValue = CMIUtilString::Format( "%lld", vnValue ); - break; - case eVarFormat_Hex: - strFormattedValue = CMIUtilString::Format( "0x%llx", vnValue ); - break; - case eVarFormat_Natural: - default: - { - strFormattedValue = (vpStrValueNatural != nullptr) ? vpStrValueNatural : ""; - } - } - - return strFormattedValue; +// Details: Return nuber formatted string according to the given value type. +// Type: Static method. +// Args: vnValue - (R) The number value to get formatted. +// vpStrValueNatural - (R) The natural representation of the number value. +// veVarFormat - (R) Var format enumeration. +// Returns: CMIUtilString - Numerical formatted string. +// Throws: None. +//-- +CMIUtilString +CMICmnLLDBDebugSessionInfoVarObj::GetStringFormatted(const MIuint64 vnValue, const MIchar *vpStrValueNatural, + const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat) +{ + CMIUtilString strFormattedValue; + + switch (veVarFormat) + { + case eVarFormat_Binary: + strFormattedValue = CMIUtilString::FormatBinary(vnValue); + break; + case eVarFormat_Octal: + strFormattedValue = CMIUtilString::Format("0%llo", vnValue); + break; + case eVarFormat_Decimal: + strFormattedValue = CMIUtilString::Format("%lld", vnValue); + break; + case eVarFormat_Hex: + strFormattedValue = CMIUtilString::Format("0x%llx", vnValue); + break; + case eVarFormat_Natural: + default: + { + strFormattedValue = (vpStrValueNatural != nullptr) ? vpStrValueNatural : ""; + } + } + + return strFormattedValue; } //++ ------------------------------------------------------------------------------------ -// Details: Delete internal container contents. -// Type: Static method. -// Args: None. -// Returns: None. -// Throws: None. +// Details: Delete internal container contents. +// Type: Static method. +// Args: None. +// Returns: None. +// Throws: None. //-- -void CMICmnLLDBDebugSessionInfoVarObj::VarObjClear( void ) +void +CMICmnLLDBDebugSessionInfoVarObj::VarObjClear(void) { - ms_mapVarIdToVarObj.clear(); + ms_mapVarIdToVarObj.clear(); } //++ ------------------------------------------------------------------------------------ -// Details: Add a var object to the internal container. -// Type: Static method. -// Args: vrVarObj - (R) The var value object. -// Returns: None. -// Throws: None. -//-- -void CMICmnLLDBDebugSessionInfoVarObj::VarObjAdd( const CMICmnLLDBDebugSessionInfoVarObj & vrVarObj ) -{ - VarObjDelete( vrVarObj.GetName() ); - MapPairKeyToVarObj_t pr( vrVarObj.GetName(), vrVarObj ); - ms_mapVarIdToVarObj.insert( pr ); +// Details: Add a var object to the internal container. +// Type: Static method. +// Args: vrVarObj - (R) The var value object. +// Returns: None. +// Throws: None. +//-- +void +CMICmnLLDBDebugSessionInfoVarObj::VarObjAdd(const CMICmnLLDBDebugSessionInfoVarObj &vrVarObj) +{ + VarObjDelete(vrVarObj.GetName()); + MapPairKeyToVarObj_t pr(vrVarObj.GetName(), vrVarObj); + ms_mapVarIdToVarObj.insert(pr); } - + //++ ------------------------------------------------------------------------------------ -// Details: Delete the var object from the internal container matching the specified name. -// Type: Static method. -// Args: vrVarName - (R) The var value name. -// Returns: None. -// Throws: None. -//-- -void CMICmnLLDBDebugSessionInfoVarObj::VarObjDelete( const CMIUtilString & vrVarName ) -{ - const MapKeyToVarObj_t::const_iterator it = ms_mapVarIdToVarObj.find( vrVarName ); - if( it != ms_mapVarIdToVarObj.end() ) - { - ms_mapVarIdToVarObj.erase( it ); - } +// Details: Delete the var object from the internal container matching the specified name. +// Type: Static method. +// Args: vrVarName - (R) The var value name. +// Returns: None. +// Throws: None. +//-- +void +CMICmnLLDBDebugSessionInfoVarObj::VarObjDelete(const CMIUtilString &vrVarName) +{ + const MapKeyToVarObj_t::const_iterator it = ms_mapVarIdToVarObj.find(vrVarName); + if (it != ms_mapVarIdToVarObj.end()) + { + ms_mapVarIdToVarObj.erase(it); + } } //++ ------------------------------------------------------------------------------------ -// Details: Update an existing var object in the internal container. -// Type: Static method. -// Args: vrVarObj - (R) The var value object. -// Returns: None. -// Throws: None. +// Details: Update an existing var object in the internal container. +// Type: Static method. +// Args: vrVarObj - (R) The var value object. +// Returns: None. +// Throws: None. //-- -void CMICmnLLDBDebugSessionInfoVarObj::VarObjUpdate( const CMICmnLLDBDebugSessionInfoVarObj & vrVarObj ) +void +CMICmnLLDBDebugSessionInfoVarObj::VarObjUpdate(const CMICmnLLDBDebugSessionInfoVarObj &vrVarObj) { - VarObjAdd( vrVarObj ); + VarObjAdd(vrVarObj); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the var object matching the specified name. -// Type: Static method. -// Args: vrVarName - (R) The var value name. -// vrwVarObj - (W) A var object. -// Returns: bool - True = object found, false = object not found. -// Throws: None. -//-- -bool CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( const CMIUtilString & vrVarName, CMICmnLLDBDebugSessionInfoVarObj & vrwVarObj ) -{ - const MapKeyToVarObj_t::const_iterator it = ms_mapVarIdToVarObj.find( vrVarName ); - if( it != ms_mapVarIdToVarObj.end() ) - { - const CMICmnLLDBDebugSessionInfoVarObj & rVarObj = (*it).second; - vrwVarObj = rVarObj; - return true; - } - - return false; +// Details: Retrieve the var object matching the specified name. +// Type: Static method. +// Args: vrVarName - (R) The var value name. +// vrwVarObj - (W) A var object. +// Returns: bool - True = object found, false = object not found. +// Throws: None. +//-- +bool +CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(const CMIUtilString &vrVarName, CMICmnLLDBDebugSessionInfoVarObj &vrwVarObj) +{ + const MapKeyToVarObj_t::const_iterator it = ms_mapVarIdToVarObj.find(vrVarName); + if (it != ms_mapVarIdToVarObj.end()) + { + const CMICmnLLDBDebugSessionInfoVarObj &rVarObj = (*it).second; + vrwVarObj = rVarObj; + return true; + } + + return false; } //++ ------------------------------------------------------------------------------------ -// Details: A count is kept of the number of var value objects created. This is count is -// used to ID the var value object. Reset the count to 0. -// Type: Static method. -// Args: None. -// Returns: None. -// Throws: None. -//-- -void CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero( void ) +// Details: A count is kept of the number of var value objects created. This is count is +// used to ID the var value object. Reset the count to 0. +// Type: Static method. +// Args: None. +// Returns: None. +// Throws: None. +//-- +void +CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero(void) { - ms_nVarUniqueId = 0; + ms_nVarUniqueId = 0; } //++ ------------------------------------------------------------------------------------ -// Details: A count is kept of the number of var value objects created. This is count is -// used to ID the var value object. Increment the count by 1. -// Type: Static method. -// Args: None. -// Returns: None. -// Throws: None. -//-- -void CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc( void ) +// Details: A count is kept of the number of var value objects created. This is count is +// used to ID the var value object. Increment the count by 1. +// Type: Static method. +// Args: None. +// Returns: None. +// Throws: None. +//-- +void +CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc(void) { - ms_nVarUniqueId++; + ms_nVarUniqueId++; } //++ ------------------------------------------------------------------------------------ -// Details: A count is kept of the number of var value objects created. This is count is -// used to ID the var value object. Retrieve ID. -// Type: Static method. -// Args: None. -// Returns: None. -// Throws: None. -//-- -MIuint CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet( void ) +// Details: A count is kept of the number of var value objects created. This is count is +// used to ID the var value object. Retrieve ID. +// Type: Static method. +// Args: None. +// Returns: None. +// Throws: None. +//-- +MIuint +CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet(void) { - return ms_nVarUniqueId; + return ms_nVarUniqueId; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the value formatted object's name. -// Type: Method. -// Args: None. -// Returns: CMIUtilString & - Value's var%u name text. -// Throws: None. +// Details: Retrieve the value formatted object's name. +// Type: Method. +// Args: None. +// Returns: CMIUtilString & - Value's var%u name text. +// Throws: None. //-- -const CMIUtilString & CMICmnLLDBDebugSessionInfoVarObj::GetName( void ) const +const CMIUtilString & +CMICmnLLDBDebugSessionInfoVarObj::GetName(void) const { - return m_strName; + return m_strName; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the value formatted object's variable name as given in the MI command -// to create the var object. -// Type: Method. -// Args: None. -// Returns: CMIUtilString & - Value's real name text. -// Throws: None. -//-- -const CMIUtilString & CMICmnLLDBDebugSessionInfoVarObj::GetNameReal( void ) const +// Details: Retrieve the value formatted object's variable name as given in the MI command +// to create the var object. +// Type: Method. +// Args: None. +// Returns: CMIUtilString & - Value's real name text. +// Throws: None. +//-- +const CMIUtilString & +CMICmnLLDBDebugSessionInfoVarObj::GetNameReal(void) const { - return m_strNameReal; + return m_strNameReal; } - + //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the value formatted string. -// Type: Method. -// Args: None. -// Returns: CMIUtilString & - Value formatted string. -// Throws: None. +// Details: Retrieve the value formatted string. +// Type: Method. +// Args: None. +// Returns: CMIUtilString & - Value formatted string. +// Throws: None. //-- -const CMIUtilString & CMICmnLLDBDebugSessionInfoVarObj::GetValueFormatted( void ) const +const CMIUtilString & +CMICmnLLDBDebugSessionInfoVarObj::GetValueFormatted(void) const { - return m_strFormattedValue; + return m_strFormattedValue; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the LLDB Value object. -// Type: Method. -// Args: None. -// Returns: lldb::SBValue & - LLDB Value object. -// Throws: None. +// Details: Retrieve the LLDB Value object. +// Type: Method. +// Args: None. +// Returns: lldb::SBValue & - LLDB Value object. +// Throws: None. //-- -const lldb::SBValue & CMICmnLLDBDebugSessionInfoVarObj::GetValue( void ) const +const lldb::SBValue & +CMICmnLLDBDebugSessionInfoVarObj::GetValue(void) const { - return m_SBValue; + return m_SBValue; } //++ ------------------------------------------------------------------------------------ -// Details: Set the var format type for *this object and upate the formatting. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugSessionInfoVarObj::SetVarFormat( const varFormat_e veVarFormat ) -{ - if( veVarFormat >= eVarFormat_count ) - return MIstatus::failure; - - m_eVarFormat = veVarFormat; - UpdateValue(); - return MIstatus::success; +// Details: Set the var format type for *this object and upate the formatting. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. +//-- +bool +CMICmnLLDBDebugSessionInfoVarObj::SetVarFormat(const varFormat_e veVarFormat) +{ + if (veVarFormat >= eVarFormat_count) + return MIstatus::failure; + + m_eVarFormat = veVarFormat; + UpdateValue(); + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Update *this var obj. Update it's value and type. -// Type: Method. -// Args: None. -// Returns: None. -// Throws: None. +// Details: Update *this var obj. Update it's value and type. +// Type: Method. +// Args: None. +// Returns: None. +// Throws: None. //-- -void CMICmnLLDBDebugSessionInfoVarObj::UpdateValue( void ) +void +CMICmnLLDBDebugSessionInfoVarObj::UpdateValue(void) { - m_strFormattedValue = CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted( m_SBValue, m_eVarFormat ); + m_strFormattedValue = CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(m_SBValue, m_eVarFormat); - MIuint64 nValue = 0; - if( CMICmnLLDBProxySBValue::GetValueAsUnsigned( m_SBValue, nValue ) == MIstatus::failure ) - m_eVarType = eVarType_Composite; + MIuint64 nValue = 0; + if (CMICmnLLDBProxySBValue::GetValueAsUnsigned(m_SBValue, nValue) == MIstatus::failure) + m_eVarType = eVarType_Composite; - CMICmnLLDBDebugSessionInfoVarObj::VarObjUpdate( *this ); + CMICmnLLDBDebugSessionInfoVarObj::VarObjUpdate(*this); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the enumeration type of the var object. -// Type: Method. -// Args: None. -// Returns: varType_e - Enumeration value. -// Throws: None. +// Details: Retrieve the enumeration type of the var object. +// Type: Method. +// Args: None. +// Returns: varType_e - Enumeration value. +// Throws: None. //-- -CMICmnLLDBDebugSessionInfoVarObj::varType_e CMICmnLLDBDebugSessionInfoVarObj::GetType( void ) const +CMICmnLLDBDebugSessionInfoVarObj::varType_e +CMICmnLLDBDebugSessionInfoVarObj::GetType(void) const { - return m_eVarType; + return m_eVarType; } - + //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the parent var object's name, the parent var object to *this var -// object (if assigned). The parent is equivalent to LLDB SBValue variable's -// parent. -// Type: Method. -// Args: None. -// Returns: CMIUtilString & - Pointer to var object, NULL = no parent. -// Throws: None. -//-- -const CMIUtilString & CMICmnLLDBDebugSessionInfoVarObj::GetVarParentName( void ) const -{ - return m_strVarObjParentName; +// Details: Retrieve the parent var object's name, the parent var object to *this var +// object (if assigned). The parent is equivalent to LLDB SBValue variable's +// parent. +// Type: Method. +// Args: None. +// Returns: CMIUtilString & - Pointer to var object, NULL = no parent. +// Throws: None. +//-- +const CMIUtilString & +CMICmnLLDBDebugSessionInfoVarObj::GetVarParentName(void) const +{ + return m_strVarObjParentName; } - \ No newline at end of file diff --git a/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h b/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h index 1db7bd8daa05..94f62a42aa6a 100644 --- a/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h +++ b/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLLDBDebugSessionInfoVarObj.h +// File: MICmnLLDBDebugSessionInfoVarObj.h // -// Overview: CMICmnLLDBDebugSessionInfoVarObj interface. +// Overview: CMICmnLLDBDebugSessionInfoVarObj interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -29,111 +29,113 @@ #include "MIUtilString.h" //++ ============================================================================ -// Details: MI debug session variable object. The static functionality in *this -// class manages a map container of *these variable objects. -// Gotchas: None. -// Authors: Illya Rudkin 24/03/2014. -// Changes: None. +// Details: MI debug session variable object. The static functionality in *this +// class manages a map container of *these variable objects. +// Gotchas: None. +// Authors: Illya Rudkin 24/03/2014. +// Changes: None. //-- class CMICmnLLDBDebugSessionInfoVarObj { -// Enums: -public: - //++ ---------------------------------------------------------------------- - // Details: Enumeration of a variable type that is not a composite type - //-- - enum varFormat_e - { - // CODETAG_SESSIONINFO_VARFORMAT_ENUM - // *** Order is import here *** - eVarFormat_Invalid = 0, - eVarFormat_Binary, - eVarFormat_Octal, - eVarFormat_Decimal, - eVarFormat_Hex, - eVarFormat_Natural, - eVarFormat_count // Always last one - }; + // Enums: + public: + //++ ---------------------------------------------------------------------- + // Details: Enumeration of a variable type that is not a composite type + //-- + enum varFormat_e + { + // CODETAG_SESSIONINFO_VARFORMAT_ENUM + // *** Order is import here *** + eVarFormat_Invalid = 0, + eVarFormat_Binary, + eVarFormat_Octal, + eVarFormat_Decimal, + eVarFormat_Hex, + eVarFormat_Natural, + eVarFormat_count // Always last one + }; - //++ ---------------------------------------------------------------------- - // Details: Enumeration of a variable type by composite or internal type - //-- - enum varType_e - { - eVarType_InValid = 0, - eVarType_Composite, // i.e. struct - eVarType_Internal, // i.e. int - eVarType_count // Always last one - }; + //++ ---------------------------------------------------------------------- + // Details: Enumeration of a variable type by composite or internal type + //-- + enum varType_e + { + eVarType_InValid = 0, + eVarType_Composite, // i.e. struct + eVarType_Internal, // i.e. int + eVarType_count // Always last one + }; -// Statics: -public: - static varFormat_e GetVarFormatForString( const CMIUtilString & vrStrFormat ); - static varFormat_e GetVarFormatForChar( const MIchar & vrcFormat ); - static CMIUtilString GetValueStringFormatted( const lldb::SBValue & vrValue, const varFormat_e veVarFormat ); - static void VarObjAdd( const CMICmnLLDBDebugSessionInfoVarObj & vrVarObj ); - static void VarObjDelete( const CMIUtilString & vrVarName ); - static bool VarObjGet( const CMIUtilString & vrVarName, CMICmnLLDBDebugSessionInfoVarObj & vrwVarObj ); - static void VarObjUpdate( const CMICmnLLDBDebugSessionInfoVarObj & vrVarObj ); - static void VarObjIdInc( void ); - static MIuint VarObjIdGet( void ); - static void VarObjIdResetToZero( void ); - static void VarObjClear( void ); + // Statics: + public: + static varFormat_e GetVarFormatForString(const CMIUtilString &vrStrFormat); + static varFormat_e GetVarFormatForChar(const MIchar &vrcFormat); + static CMIUtilString GetValueStringFormatted(const lldb::SBValue &vrValue, const varFormat_e veVarFormat); + static void VarObjAdd(const CMICmnLLDBDebugSessionInfoVarObj &vrVarObj); + static void VarObjDelete(const CMIUtilString &vrVarName); + static bool VarObjGet(const CMIUtilString &vrVarName, CMICmnLLDBDebugSessionInfoVarObj &vrwVarObj); + static void VarObjUpdate(const CMICmnLLDBDebugSessionInfoVarObj &vrVarObj); + static void VarObjIdInc(void); + static MIuint VarObjIdGet(void); + static void VarObjIdResetToZero(void); + static void VarObjClear(void); -// Methods: -public: - /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( void ); - /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( const CMIUtilString & vrStrNameReal, const CMIUtilString & vrStrName, const lldb::SBValue & vrValue ); - /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( const CMIUtilString & vrStrNameReal, const CMIUtilString & vrStrName, const lldb::SBValue & vrValue, const CMIUtilString & vrStrVarObjParentName ); - /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( const CMICmnLLDBDebugSessionInfoVarObj & vrOther ); - /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( CMICmnLLDBDebugSessionInfoVarObj & vrOther ); - /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( CMICmnLLDBDebugSessionInfoVarObj && vrOther ); - // - CMICmnLLDBDebugSessionInfoVarObj & operator= ( const CMICmnLLDBDebugSessionInfoVarObj & vrOther ); - CMICmnLLDBDebugSessionInfoVarObj & operator= ( CMICmnLLDBDebugSessionInfoVarObj && vrwOther ); - // - const CMIUtilString & GetName( void ) const; - const CMIUtilString & GetNameReal( void ) const; - const CMIUtilString & GetValueFormatted( void ) const; - const lldb::SBValue & GetValue( void ) const; - varType_e GetType( void ) const; - bool SetVarFormat( const varFormat_e veVarFormat ); - const CMIUtilString & GetVarParentName( void ) const; - void UpdateValue( void ); + // Methods: + public: + /* ctor */ CMICmnLLDBDebugSessionInfoVarObj(void); + /* ctor */ CMICmnLLDBDebugSessionInfoVarObj(const CMIUtilString &vrStrNameReal, const CMIUtilString &vrStrName, + const lldb::SBValue &vrValue); + /* ctor */ CMICmnLLDBDebugSessionInfoVarObj(const CMIUtilString &vrStrNameReal, const CMIUtilString &vrStrName, + const lldb::SBValue &vrValue, const CMIUtilString &vrStrVarObjParentName); + /* ctor */ CMICmnLLDBDebugSessionInfoVarObj(const CMICmnLLDBDebugSessionInfoVarObj &vrOther); + /* ctor */ CMICmnLLDBDebugSessionInfoVarObj(CMICmnLLDBDebugSessionInfoVarObj &vrOther); + /* ctor */ CMICmnLLDBDebugSessionInfoVarObj(CMICmnLLDBDebugSessionInfoVarObj &&vrOther); + // + CMICmnLLDBDebugSessionInfoVarObj &operator=(const CMICmnLLDBDebugSessionInfoVarObj &vrOther); + CMICmnLLDBDebugSessionInfoVarObj &operator=(CMICmnLLDBDebugSessionInfoVarObj &&vrwOther); + // + const CMIUtilString &GetName(void) const; + const CMIUtilString &GetNameReal(void) const; + const CMIUtilString &GetValueFormatted(void) const; + const lldb::SBValue &GetValue(void) const; + varType_e GetType(void) const; + bool SetVarFormat(const varFormat_e veVarFormat); + const CMIUtilString &GetVarParentName(void) const; + void UpdateValue(void); -// Overridden: -public: - // From CMICmnBase - /* dtor */ virtual ~CMICmnLLDBDebugSessionInfoVarObj( void ); + // Overridden: + public: + // From CMICmnBase + /* dtor */ virtual ~CMICmnLLDBDebugSessionInfoVarObj(void); -// Typedefs: -private: - typedef std::map< CMIUtilString, CMICmnLLDBDebugSessionInfoVarObj > MapKeyToVarObj_t; - typedef std::pair< CMIUtilString, CMICmnLLDBDebugSessionInfoVarObj > MapPairKeyToVarObj_t; + // Typedefs: + private: + typedef std::map MapKeyToVarObj_t; + typedef std::pair MapPairKeyToVarObj_t; -// Statics: -private: - static CMIUtilString GetStringFormatted( const MIuint64 vnValue, const MIchar * vpStrValueNatural, varFormat_e veVarFormat ); - -// Methods: -private: - bool CopyOther( const CMICmnLLDBDebugSessionInfoVarObj & vrOther ); - bool MoveOther( CMICmnLLDBDebugSessionInfoVarObj & vrwOther ); + // Statics: + private: + static CMIUtilString GetStringFormatted(const MIuint64 vnValue, const MIchar *vpStrValueNatural, varFormat_e veVarFormat); -// Attributes: -private: - static const MIchar * ms_aVarFormatStrings[]; - static const MIchar * ms_aVarFormatChars[]; - static MapKeyToVarObj_t ms_mapVarIdToVarObj; - static MIuint ms_nVarUniqueId; - // - // *** Upate the copy move constructors and assignment operator *** - varFormat_e m_eVarFormat; - varType_e m_eVarType; - CMIUtilString m_strName; - lldb::SBValue m_SBValue; - CMIUtilString m_strNameReal; - CMIUtilString m_strFormattedValue; - CMIUtilString m_strVarObjParentName; - // *** Upate the copy move constructors and assignment operator *** + // Methods: + private: + bool CopyOther(const CMICmnLLDBDebugSessionInfoVarObj &vrOther); + bool MoveOther(CMICmnLLDBDebugSessionInfoVarObj &vrwOther); + + // Attributes: + private: + static const MIchar *ms_aVarFormatStrings[]; + static const MIchar *ms_aVarFormatChars[]; + static MapKeyToVarObj_t ms_mapVarIdToVarObj; + static MIuint ms_nVarUniqueId; + // + // *** Upate the copy move constructors and assignment operator *** + varFormat_e m_eVarFormat; + varType_e m_eVarType; + CMIUtilString m_strName; + lldb::SBValue m_SBValue; + CMIUtilString m_strNameReal; + CMIUtilString m_strFormattedValue; + CMIUtilString m_strVarObjParentName; + // *** Upate the copy move constructors and assignment operator *** }; diff --git a/tools/lldb-mi/MICmnLLDBDebugger.cpp b/tools/lldb-mi/MICmnLLDBDebugger.cpp index f68f5083054b..273b805156f4 100644 --- a/tools/lldb-mi/MICmnLLDBDebugger.cpp +++ b/tools/lldb-mi/MICmnLLDBDebugger.cpp @@ -8,20 +8,20 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLLDBDebugger.cpp +// File: MICmnLLDBDebugger.cpp // -// Overview: CMICmnLLDBDebugger implementation. +// Overview: CMICmnLLDBDebugger implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third party headers: #include -#include +#include #include #include @@ -36,672 +36,693 @@ #include "MIUtilSingletonHelper.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBDebugger constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnLLDBDebugger constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnLLDBDebugger::CMICmnLLDBDebugger( void ) -: m_constStrThisThreadId( "MI debugger event" ) +CMICmnLLDBDebugger::CMICmnLLDBDebugger(void) + : m_constStrThisThreadId("MI debugger event") { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBDebugger destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnLLDBDebugger destructor. +// Type: Overridable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnLLDBDebugger::~CMICmnLLDBDebugger( void ) +CMICmnLLDBDebugger::~CMICmnLLDBDebugger(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this debugger object. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Initialize resources for *this debugger object. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::Initialize( void ) +bool +CMICmnLLDBDebugger::Initialize(void) { - m_clientUsageRefCnt++; - - if( m_bInitialized ) - return MIstatus::success; - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - ClrErrorDescription(); - - if( m_pClientDriver == nullptr ) - { - bOk = false; - errMsg = MIRSRC( IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER ); - } - - // Note initialization order is important here as some resources depend on previous - MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); - MI::ModuleInit< CMICmnResources > ( IDS_MI_INIT_ERR_RESOURCES , bOk, errMsg ); - MI::ModuleInit< CMICmnThreadMgrStd > ( IDS_MI_INIT_ERR_THREADMGR , bOk, errMsg ); - MI::ModuleInit< CMICmnLLDBDebuggerHandleEvents >( IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg ); - MI::ModuleInit< CMICmnLLDBDebugSessionInfo > ( IDS_MI_INIT_ERR_DEBUGSESSIONINFO, bOk, errMsg ); - - // Note order is important here! - if( bOk ) - lldb::SBDebugger::Initialize(); - if( bOk && !InitSBDebugger() ) - { - bOk = false; - if( !errMsg.empty() ) errMsg += ", "; - errMsg += GetErrorDescription().c_str(); - } - if( bOk && !InitSBListener() ) - { - bOk = false; - if( !errMsg.empty() ) errMsg += ", "; - errMsg += GetErrorDescription().c_str(); - } - bOk = bOk && InitStdStreams(); - - m_bInitialized = bOk; - - if( !bOk && !HaveErrorDescription() ) - { - CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_LLDBDEBUGGER ), errMsg.c_str() ) ); - SetErrorDescription( strInitError ); - } - - return bOk; + m_clientUsageRefCnt++; + + if (m_bInitialized) + return MIstatus::success; + + bool bOk = MIstatus::success; + CMIUtilString errMsg; + ClrErrorDescription(); + + if (m_pClientDriver == nullptr) + { + bOk = false; + errMsg = MIRSRC(IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER); + } + + // Note initialization order is important here as some resources depend on previous + MI::ModuleInit(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_THREADMGR, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_DEBUGSESSIONINFO, bOk, errMsg); + + // Note order is important here! + if (bOk) + lldb::SBDebugger::Initialize(); + if (bOk && !InitSBDebugger()) + { + bOk = false; + if (!errMsg.empty()) + errMsg += ", "; + errMsg += GetErrorDescription().c_str(); + } + if (bOk && !InitSBListener()) + { + bOk = false; + if (!errMsg.empty()) + errMsg += ", "; + errMsg += GetErrorDescription().c_str(); + } + bOk = bOk && InitStdStreams(); + + m_bInitialized = bOk; + + if (!bOk && !HaveErrorDescription()) + { + CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_LLDBDEBUGGER), errMsg.c_str())); + SetErrorDescription(strInitError); + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this debugger object. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Release resources for *this debugger object. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::Shutdown( void ) +bool +CMICmnLLDBDebugger::Shutdown(void) { - if( --m_clientUsageRefCnt > 0 ) - return MIstatus::success; - - if( !m_bInitialized ) - return MIstatus::success; - - m_bInitialized = false; - - ClrErrorDescription(); - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Explicitly delete the remote target in case MI needs to exit prematurely otherwise - // LLDB debugger may hang in its Destroy() fn waiting on events - m_lldbDebugger.DeleteTarget( CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget ); - - // Debug: May need this but does seem to work without it so commented out the fudge 19/06/2014 - // It appears we need to wait as hang does not occur when hitting a debug breakpoint here - //const std::chrono::milliseconds time( 1000 ); - //std::this_thread::sleep_for( time ); - - lldb::SBDebugger::Destroy( m_lldbDebugger ); - lldb::SBDebugger::Terminate(); - m_pClientDriver = nullptr; - m_mapBroadcastClassNameToEventMask.clear(); - m_mapIdToEventMask.clear(); - - // Note shutdown order is important here - MI::ModuleShutdown< CMICmnLLDBDebugSessionInfo > ( IDS_MI_INIT_ERR_DEBUGSESSIONINFO, bOk, errMsg ); - MI::ModuleShutdown< CMICmnLLDBDebuggerHandleEvents >( IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg ); - MI::ModuleShutdown< CMICmnThreadMgrStd > ( IDS_MI_INIT_ERR_THREADMGR , bOk, errMsg ); - MI::ModuleShutdown< CMICmnResources > ( IDS_MI_INIT_ERR_RESOURCES , bOk, errMsg ); - MI::ModuleShutdown< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); - - if( !bOk ) - { - SetErrorDescriptionn( MIRSRC( IDS_MI_SHTDWN_ERR_LLDBDEBUGGER ), errMsg.c_str() ); - } - - return MIstatus::success; -} + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; + + if (!m_bInitialized) + return MIstatus::success; + + m_bInitialized = false; + + ClrErrorDescription(); + + bool bOk = MIstatus::success; + CMIUtilString errMsg; + + // Explicitly delete the remote target in case MI needs to exit prematurely otherwise + // LLDB debugger may hang in its Destroy() fn waiting on events + m_lldbDebugger.DeleteTarget(CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget); + + // Debug: May need this but does seem to work without it so commented out the fudge 19/06/2014 + // It appears we need to wait as hang does not occur when hitting a debug breakpoint here + // const std::chrono::milliseconds time( 1000 ); + // std::this_thread::sleep_for( time ); + + lldb::SBDebugger::Destroy(m_lldbDebugger); + lldb::SBDebugger::Terminate(); + m_pClientDriver = nullptr; + m_mapBroadcastClassNameToEventMask.clear(); + m_mapIdToEventMask.clear(); + + // Note shutdown order is important here + MI::ModuleShutdown(IDS_MI_INIT_ERR_DEBUGSESSIONINFO, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_INIT_ERR_THREADMGR, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + + if (!bOk) + { + SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_LLDBDEBUGGER), errMsg.c_str()); + } + + return MIstatus::success; +} //++ ------------------------------------------------------------------------------------ -// Details: Return the LLDB debugger instance created for this debug session. -// Type: Method. -// Args: None. -// Return: lldb::SBDebugger & - LLDB debugger object reference. -// Throws: None. +// Details: Return the LLDB debugger instance created for this debug session. +// Type: Method. +// Args: None. +// Return: lldb::SBDebugger & - LLDB debugger object reference. +// Throws: None. //-- -lldb::SBDebugger & CMICmnLLDBDebugger::GetTheDebugger( void ) +lldb::SBDebugger & +CMICmnLLDBDebugger::GetTheDebugger(void) { - return m_lldbDebugger; + return m_lldbDebugger; } //++ ------------------------------------------------------------------------------------ -// Details: Return the LLDB listener instance created for this debug session. -// Type: Method. -// Args: None. -// Return: lldb::SBListener & - LLDB listener object reference. -// Throws: None. +// Details: Return the LLDB listener instance created for this debug session. +// Type: Method. +// Args: None. +// Return: lldb::SBListener & - LLDB listener object reference. +// Throws: None. //-- -lldb::SBListener & CMICmnLLDBDebugger::GetTheListener( void ) +lldb::SBListener & +CMICmnLLDBDebugger::GetTheListener(void) { - return m_lldbListener; + return m_lldbListener; } //++ ------------------------------------------------------------------------------------ -// Details: Set the client driver that wants to use *this LLDB debugger. Call this function -// prior to Initialize(). -// Type: Method. -// Args: vClientDriver - (R) A driver. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Set the client driver that wants to use *this LLDB debugger. Call this function +// prior to Initialize(). +// Type: Method. +// Args: vClientDriver - (R) A driver. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::SetDriver( const CMIDriverBase & vClientDriver ) +bool +CMICmnLLDBDebugger::SetDriver(const CMIDriverBase &vClientDriver) { - m_pClientDriver = const_cast< CMIDriverBase * >( &vClientDriver ); + m_pClientDriver = const_cast(&vClientDriver); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Get the client driver that is use *this LLDB debugger. -// Type: Method. -// Args: vClientDriver - (R) A driver. -// Return: CMIDriverBase & - A driver instance. -// Throws: None. +// Details: Get the client driver that is use *this LLDB debugger. +// Type: Method. +// Args: vClientDriver - (R) A driver. +// Return: CMIDriverBase & - A driver instance. +// Throws: None. //-- -CMIDriverBase & CMICmnLLDBDebugger::GetDriver( void ) const +CMIDriverBase & +CMICmnLLDBDebugger::GetDriver(void) const { - return *m_pClientDriver; + return *m_pClientDriver; } - + //++ ------------------------------------------------------------------------------------ -// Details: Initialize the LLDB Debugger object. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Initialize the LLDB Debugger object. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::InitSBDebugger( void ) +bool +CMICmnLLDBDebugger::InitSBDebugger(void) { - m_lldbDebugger = lldb::SBDebugger::Create( false ); - if( m_lldbDebugger.IsValid() ) - return MIstatus::success; + m_lldbDebugger = lldb::SBDebugger::Create(false); + if (m_lldbDebugger.IsValid()) + return MIstatus::success; - SetErrorDescription( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER ) ); - return MIstatus::failure; + SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER)); + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Set the LLDB Debugger's std in, err and out streams. (Not implemented left -// here for reference. Was called in the CMICmnLLDBDebugger::Initialize() ) -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Set the LLDB Debugger's std in, err and out streams. (Not implemented left +// here for reference. Was called in the CMICmnLLDBDebugger::Initialize() ) +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::InitStdStreams( void ) +bool +CMICmnLLDBDebugger::InitStdStreams(void) { - // This is not required when operating the MI driver's code as it has its own - // streams. Setting the Stdin for the lldbDebugger especially on LINUX will cause - // another thread to run and partially consume stdin data meant for MI stdin handler - //m_lldbDebugger.SetErrorFileHandle( m_pClientDriver->GetStderr(), false ); - //m_lldbDebugger.SetOutputFileHandle( m_pClientDriver->GetStdout(), false ); - //m_lldbDebugger.SetInputFileHandle( m_pClientDriver->GetStdin(), false ); - - return MIstatus::success; + // This is not required when operating the MI driver's code as it has its own + // streams. Setting the Stdin for the lldbDebugger especially on LINUX will cause + // another thread to run and partially consume stdin data meant for MI stdin handler + // m_lldbDebugger.SetErrorFileHandle( m_pClientDriver->GetStderr(), false ); + // m_lldbDebugger.SetOutputFileHandle( m_pClientDriver->GetStdout(), false ); + // m_lldbDebugger.SetInputFileHandle( m_pClientDriver->GetStdin(), false ); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Set up the events from the SBDebugger's we would to listent to. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::InitSBListener( void ) +bool +CMICmnLLDBDebugger::InitSBListener(void) { - m_lldbListener = m_lldbDebugger.GetListener(); - if( !m_lldbListener.IsValid() ) - { - SetErrorDescription( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER ) ); - return MIstatus::failure; - } - - const CMIUtilString strDbgId( "CMICmnLLDBDebugger1" ); - MIuint eventMask = lldb::SBTarget::eBroadcastBitBreakpointChanged; - bool bOk = RegisterForEvent( strDbgId, CMIUtilString( lldb::SBTarget::GetBroadcasterClassName() ), eventMask ); - - eventMask = lldb::SBThread::eBroadcastBitStackChanged; - bOk = bOk && RegisterForEvent( strDbgId, CMIUtilString( lldb::SBThread::GetBroadcasterClassName() ), eventMask ); - - eventMask = lldb::SBProcess::eBroadcastBitStateChanged | - lldb::SBProcess::eBroadcastBitInterrupt | - lldb::SBProcess::eBroadcastBitSTDOUT | - lldb::SBProcess::eBroadcastBitSTDERR | - lldb::SBProcess::eBroadcastBitProfileData; - bOk = bOk && RegisterForEvent( strDbgId, CMIUtilString( lldb::SBProcess::GetBroadcasterClassName() ), eventMask ); - - eventMask = lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived | - lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit | - lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData | - lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData; - bOk = bOk && RegisterForEvent( strDbgId, CMIUtilString( lldb::SBCommandInterpreter::GetBroadcasterClass() ), eventMask ); - - return bOk; + m_lldbListener = m_lldbDebugger.GetListener(); + if (!m_lldbListener.IsValid()) + { + SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER)); + return MIstatus::failure; + } + + const CMIUtilString strDbgId("CMICmnLLDBDebugger1"); + MIuint eventMask = lldb::SBTarget::eBroadcastBitBreakpointChanged; + bool bOk = RegisterForEvent(strDbgId, CMIUtilString(lldb::SBTarget::GetBroadcasterClassName()), eventMask); + + eventMask = lldb::SBThread::eBroadcastBitStackChanged; + bOk = bOk && RegisterForEvent(strDbgId, CMIUtilString(lldb::SBThread::GetBroadcasterClassName()), eventMask); + + eventMask = lldb::SBProcess::eBroadcastBitStateChanged | lldb::SBProcess::eBroadcastBitInterrupt | + lldb::SBProcess::eBroadcastBitSTDOUT | lldb::SBProcess::eBroadcastBitSTDERR | lldb::SBProcess::eBroadcastBitProfileData; + bOk = bOk && RegisterForEvent(strDbgId, CMIUtilString(lldb::SBProcess::GetBroadcasterClassName()), eventMask); + + eventMask = lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived | lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit | + lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData | + lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData; + bOk = bOk && RegisterForEvent(strDbgId, CMIUtilString(lldb::SBCommandInterpreter::GetBroadcasterClass()), eventMask); + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Register with the debugger, the SBListener, the type of events you are interested -// in. Others, like commands, may have already set the mask. -// Type: Method. -// Args: vClientName - (R) ID of the client who wants these events set. -// vBroadcasterClass - (R) The SBBroadcaster's class name. -// vEventMask - (R) The mask of events to listen for. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Register with the debugger, the SBListener, the type of events you are interested +// in. Others, like commands, may have already set the mask. +// Type: Method. +// Args: vClientName - (R) ID of the client who wants these events set. +// vBroadcasterClass - (R) The SBBroadcaster's class name. +// vEventMask - (R) The mask of events to listen for. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::RegisterForEvent( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass, const MIuint vEventMask ) +bool +CMICmnLLDBDebugger::RegisterForEvent(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask) { - MIuint existingMask = 0; - if( !BroadcasterGetMask( vBroadcasterClass, existingMask ) ) - return MIstatus::failure; - - if( !ClientSaveMask( vClientName, vBroadcasterClass, vEventMask ) ) - return MIstatus::failure; - - const MIchar * pBroadCasterName = vBroadcasterClass.c_str(); - MIuint eventMask = vEventMask; - eventMask += existingMask; - const MIuint result = m_lldbListener.StartListeningForEventClass( m_lldbDebugger, pBroadCasterName, eventMask ); - if( result == 0 ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_STARTLISTENER ), pBroadCasterName ) ); - return MIstatus::failure; - } - - return BroadcasterSaveMask( vBroadcasterClass, eventMask ); + MIuint existingMask = 0; + if (!BroadcasterGetMask(vBroadcasterClass, existingMask)) + return MIstatus::failure; + + if (!ClientSaveMask(vClientName, vBroadcasterClass, vEventMask)) + return MIstatus::failure; + + const MIchar *pBroadCasterName = vBroadcasterClass.c_str(); + MIuint eventMask = vEventMask; + eventMask += existingMask; + const MIuint result = m_lldbListener.StartListeningForEventClass(m_lldbDebugger, pBroadCasterName, eventMask); + if (result == 0) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_STARTLISTENER), pBroadCasterName)); + return MIstatus::failure; + } + + return BroadcasterSaveMask(vBroadcasterClass, eventMask); } //++ ------------------------------------------------------------------------------------ -// Details: Register with the debugger, the SBListener, the type of events you are interested -// in. Others, like commands, may have already set the mask. -// Type: Method. -// Args: vClientName - (R) ID of the client who wants these events set. -// vBroadcaster - (R) An SBBroadcaster's derived class. -// vEventMask - (R) The mask of events to listen for. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Register with the debugger, the SBListener, the type of events you are interested +// in. Others, like commands, may have already set the mask. +// Type: Method. +// Args: vClientName - (R) ID of the client who wants these events set. +// vBroadcaster - (R) An SBBroadcaster's derived class. +// vEventMask - (R) The mask of events to listen for. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::RegisterForEvent( const CMIUtilString & vClientName, const lldb::SBBroadcaster & vBroadcaster, const MIuint vEventMask ) +bool +CMICmnLLDBDebugger::RegisterForEvent(const CMIUtilString &vClientName, const lldb::SBBroadcaster &vBroadcaster, const MIuint vEventMask) { - const MIchar * pBroadcasterName = vBroadcaster.GetName(); - if( pBroadcasterName == nullptr ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_BROARDCASTER_NAME ), MIRSRC( IDS_WORD_INVALIDNULLPTR ) ) ); - return MIstatus::failure; - } - CMIUtilString broadcasterName( pBroadcasterName ); - if( broadcasterName.length() == 0 ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_BROARDCASTER_NAME ), MIRSRC( IDS_WORD_INVALIDEMPTY ) ) ); - return MIstatus::failure; - } - - MIuint existingMask = 0; - if( !BroadcasterGetMask( broadcasterName, existingMask ) ) - return MIstatus::failure; - - if( !ClientSaveMask( vClientName, broadcasterName, vEventMask ) ) - return MIstatus::failure; - - MIuint eventMask = vEventMask; - eventMask += existingMask; - const MIuint result = m_lldbListener.StartListeningForEvents( vBroadcaster, eventMask ); - if( result == 0 ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_STARTLISTENER ), pBroadcasterName ) ); - return MIstatus::failure; - } - - return BroadcasterSaveMask( broadcasterName, eventMask ); + const MIchar *pBroadcasterName = vBroadcaster.GetName(); + if (pBroadcasterName == nullptr) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROARDCASTER_NAME), MIRSRC(IDS_WORD_INVALIDNULLPTR))); + return MIstatus::failure; + } + CMIUtilString broadcasterName(pBroadcasterName); + if (broadcasterName.length() == 0) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROARDCASTER_NAME), MIRSRC(IDS_WORD_INVALIDEMPTY))); + return MIstatus::failure; + } + + MIuint existingMask = 0; + if (!BroadcasterGetMask(broadcasterName, existingMask)) + return MIstatus::failure; + + if (!ClientSaveMask(vClientName, broadcasterName, vEventMask)) + return MIstatus::failure; + + MIuint eventMask = vEventMask; + eventMask += existingMask; + const MIuint result = m_lldbListener.StartListeningForEvents(vBroadcaster, eventMask); + if (result == 0) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_STARTLISTENER), pBroadcasterName)); + return MIstatus::failure; + } + + return BroadcasterSaveMask(broadcasterName, eventMask); } //++ ------------------------------------------------------------------------------------ -// Details: Unregister with the debugger, the SBListener, the type of events you are no -// longer interested in. Others, like commands, may still remain interested so -// an event may not necessarily be stopped. -// Type: Method. -// Args: vClientName - (R) ID of the client who no longer requires these events. -// vBroadcasterClass - (R) The SBBroadcaster's class name. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Unregister with the debugger, the SBListener, the type of events you are no +// longer interested in. Others, like commands, may still remain interested so +// an event may not necessarily be stopped. +// Type: Method. +// Args: vClientName - (R) ID of the client who no longer requires these events. +// vBroadcasterClass - (R) The SBBroadcaster's class name. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::UnregisterForEvent( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass ) +bool +CMICmnLLDBDebugger::UnregisterForEvent(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass) { - MIuint clientsEventMask = 0; - if( !ClientGetTheirMask( vClientName, vBroadcasterClass, clientsEventMask ) ) - return MIstatus::failure; - if( !ClientRemoveTheirMask( vClientName, vBroadcasterClass ) ) - return MIstatus::failure; - - const MIuint otherClientsEventMask = ClientGetMaskForAllClients( vBroadcasterClass ); - MIuint newEventMask = 0; - for( MIuint i = 0; i < 32; i++ ) - { - const MIuint bit = 1 << i; - const MIuint clientBit = bit & clientsEventMask; - const MIuint othersBit = bit & otherClientsEventMask; - if( (clientBit != 0) && (othersBit == 0) ) - { - newEventMask += clientBit; - } - } - - const MIchar * pBroadCasterName = vBroadcasterClass.c_str(); - if( !m_lldbListener.StopListeningForEventClass( m_lldbDebugger, pBroadCasterName, newEventMask ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_STOPLISTENER ), vClientName.c_str(), pBroadCasterName ) ); - return MIstatus::failure; - } - - return BroadcasterSaveMask( vBroadcasterClass, otherClientsEventMask ); + MIuint clientsEventMask = 0; + if (!ClientGetTheirMask(vClientName, vBroadcasterClass, clientsEventMask)) + return MIstatus::failure; + if (!ClientRemoveTheirMask(vClientName, vBroadcasterClass)) + return MIstatus::failure; + + const MIuint otherClientsEventMask = ClientGetMaskForAllClients(vBroadcasterClass); + MIuint newEventMask = 0; + for (MIuint i = 0; i < 32; i++) + { + const MIuint bit = 1 << i; + const MIuint clientBit = bit & clientsEventMask; + const MIuint othersBit = bit & otherClientsEventMask; + if ((clientBit != 0) && (othersBit == 0)) + { + newEventMask += clientBit; + } + } + + const MIchar *pBroadCasterName = vBroadcasterClass.c_str(); + if (!m_lldbListener.StopListeningForEventClass(m_lldbDebugger, pBroadCasterName, newEventMask)) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_STOPLISTENER), vClientName.c_str(), pBroadCasterName)); + return MIstatus::failure; + } + + return BroadcasterSaveMask(vBroadcasterClass, otherClientsEventMask); } //++ ------------------------------------------------------------------------------------ -// Details: Given the SBBroadcaster class name retrieve it's current event mask. -// Type: Method. -// Args: vBroadcasterClass - (R) The SBBroadcaster's class name. -// vEventMask - (W) The mask of events to listen for. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Given the SBBroadcaster class name retrieve it's current event mask. +// Type: Method. +// Args: vBroadcasterClass - (R) The SBBroadcaster's class name. +// vEventMask - (W) The mask of events to listen for. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::BroadcasterGetMask( const CMIUtilString & vBroadcasterClass, MIuint & vwEventMask ) const +bool +CMICmnLLDBDebugger::BroadcasterGetMask(const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask) const { - vwEventMask = 0; + vwEventMask = 0; - if( vBroadcasterClass.empty() ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER ), vBroadcasterClass.c_str() ) ); - return MIstatus::failure; - } + if (vBroadcasterClass.empty()) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER), vBroadcasterClass.c_str())); + return MIstatus::failure; + } - const MapBroadcastClassNameToEventMask_t::const_iterator it = m_mapBroadcastClassNameToEventMask.find( vBroadcasterClass ); - if( it != m_mapBroadcastClassNameToEventMask.end() ) - { - vwEventMask = (*it).second; - } + const MapBroadcastClassNameToEventMask_t::const_iterator it = m_mapBroadcastClassNameToEventMask.find(vBroadcasterClass); + if (it != m_mapBroadcastClassNameToEventMask.end()) + { + vwEventMask = (*it).second; + } - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Remove the event mask for the specified SBBroadcaster class name. -// Type: Method. -// Args: vBroadcasterClass - (R) The SBBroadcaster's class name. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Remove the event mask for the specified SBBroadcaster class name. +// Type: Method. +// Args: vBroadcasterClass - (R) The SBBroadcaster's class name. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::BroadcasterRemoveMask( const CMIUtilString & vBroadcasterClass ) +bool +CMICmnLLDBDebugger::BroadcasterRemoveMask(const CMIUtilString &vBroadcasterClass) { - MapBroadcastClassNameToEventMask_t::const_iterator it = m_mapBroadcastClassNameToEventMask.find( vBroadcasterClass ); - if( it != m_mapBroadcastClassNameToEventMask.end() ) - { - m_mapBroadcastClassNameToEventMask.erase( it ); - } + MapBroadcastClassNameToEventMask_t::const_iterator it = m_mapBroadcastClassNameToEventMask.find(vBroadcasterClass); + if (it != m_mapBroadcastClassNameToEventMask.end()) + { + m_mapBroadcastClassNameToEventMask.erase(it); + } - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Given the SBBroadcaster class name save it's current event mask. -// Type: Method. -// Args: vBroadcasterClass - (R) The SBBroadcaster's class name. -// vEventMask - (R) The mask of events to listen for. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Given the SBBroadcaster class name save it's current event mask. +// Type: Method. +// Args: vBroadcasterClass - (R) The SBBroadcaster's class name. +// vEventMask - (R) The mask of events to listen for. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::BroadcasterSaveMask( const CMIUtilString & vBroadcasterClass, const MIuint vEventMask ) +bool +CMICmnLLDBDebugger::BroadcasterSaveMask(const CMIUtilString &vBroadcasterClass, const MIuint vEventMask) { - if( vBroadcasterClass.empty() ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER ), vBroadcasterClass.c_str() ) ); - return MIstatus::failure; - } + if (vBroadcasterClass.empty()) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER), vBroadcasterClass.c_str())); + return MIstatus::failure; + } - BroadcasterRemoveMask( vBroadcasterClass ); - MapPairBroadcastClassNameToEventMask_t pr( vBroadcasterClass, vEventMask ); - m_mapBroadcastClassNameToEventMask.insert( pr ); + BroadcasterRemoveMask(vBroadcasterClass); + MapPairBroadcastClassNameToEventMask_t pr(vBroadcasterClass, vEventMask); + m_mapBroadcastClassNameToEventMask.insert(pr); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Iterate all the clients who have registered event masks against particular -// SBBroadcasters and build up the mask that is for all of them. -// Type: Method. -// Args: vBroadcasterClass - (R) The broadcaster to retrieve the mask for. -// Return: MIuint - Event mask. -// Throws: None. +// Details: Iterate all the clients who have registered event masks against particular +// SBBroadcasters and build up the mask that is for all of them. +// Type: Method. +// Args: vBroadcasterClass - (R) The broadcaster to retrieve the mask for. +// Return: MIuint - Event mask. +// Throws: None. //-- -MIuint CMICmnLLDBDebugger::ClientGetMaskForAllClients( const CMIUtilString & vBroadcasterClass ) const +MIuint +CMICmnLLDBDebugger::ClientGetMaskForAllClients(const CMIUtilString &vBroadcasterClass) const { - MIuint mask = 0; - MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.begin(); - while( it != m_mapIdToEventMask.end() ) - { - const CMIUtilString & rId( (*it).first ); - if( rId.find( vBroadcasterClass.c_str() ) != std::string::npos ) - { - const MIuint clientsMask = (*it).second; - mask |= clientsMask; - } - - // Next - ++it; - } - - return mask; + MIuint mask = 0; + MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.begin(); + while (it != m_mapIdToEventMask.end()) + { + const CMIUtilString &rId((*it).first); + if (rId.find(vBroadcasterClass.c_str()) != std::string::npos) + { + const MIuint clientsMask = (*it).second; + mask |= clientsMask; + } + + // Next + ++it; + } + + return mask; } //++ ------------------------------------------------------------------------------------ -// Details: Given the client save its particular event requirements. -// Type: Method. -// Args: vClientName - (R) The Client's unique ID. -// vBroadcasterClass - (R) The SBBroadcaster's class name targeted for the events. -// vEventMask - (R) The mask of events to listen for. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Given the client save its particular event requirements. +// Type: Method. +// Args: vClientName - (R) The Client's unique ID. +// vBroadcasterClass - (R) The SBBroadcaster's class name targeted for the events. +// vEventMask - (R) The mask of events to listen for. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::ClientSaveMask( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass, const MIuint vEventMask ) +bool +CMICmnLLDBDebugger::ClientSaveMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask) { - if( vClientName.empty() ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME ), vClientName.c_str() ) ); - return MIstatus::failure; - } + if (vClientName.empty()) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str())); + return MIstatus::failure; + } - CMIUtilString strId( vBroadcasterClass ); - strId += vClientName; + CMIUtilString strId(vBroadcasterClass); + strId += vClientName; - ClientRemoveTheirMask( vClientName, vBroadcasterClass ); - MapPairIdToEventMask_t pr( strId, vEventMask ); - m_mapIdToEventMask.insert( pr ); + ClientRemoveTheirMask(vClientName, vBroadcasterClass); + MapPairIdToEventMask_t pr(strId, vEventMask); + m_mapIdToEventMask.insert(pr); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Given the client remove it's particular event requirements. -// Type: Method. -// Args: vClientName - (R) The Client's unique ID. -// vBroadcasterClass - (R) The SBBroadcaster's class name. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Given the client remove it's particular event requirements. +// Type: Method. +// Args: vClientName - (R) The Client's unique ID. +// vBroadcasterClass - (R) The SBBroadcaster's class name. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::ClientRemoveTheirMask( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass ) +bool +CMICmnLLDBDebugger::ClientRemoveTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass) { - if( vClientName.empty() ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME ), vClientName.c_str() ) ); - return MIstatus::failure; - } - - CMIUtilString strId( vBroadcasterClass ); - strId += vClientName; - - const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find( strId ); - if( it != m_mapIdToEventMask.end() ) - { - m_mapIdToEventMask.erase( it ); - } - - return MIstatus::success; + if (vClientName.empty()) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str())); + return MIstatus::failure; + } + + CMIUtilString strId(vBroadcasterClass); + strId += vClientName; + + const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId); + if (it != m_mapIdToEventMask.end()) + { + m_mapIdToEventMask.erase(it); + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the client's event mask used for on a particular SBBroadcaster. -// Type: Method. -// Args: vClientName - (R) The Client's unique ID. -// vBroadcasterClass - (R) The SBBroadcaster's class name. -// vwEventMask - (W) The client's mask. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Retrieve the client's event mask used for on a particular SBBroadcaster. +// Type: Method. +// Args: vClientName - (R) The Client's unique ID. +// vBroadcasterClass - (R) The SBBroadcaster's class name. +// vwEventMask - (W) The client's mask. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::ClientGetTheirMask( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass, MIuint & vwEventMask ) +bool +CMICmnLLDBDebugger::ClientGetTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask) { - vwEventMask = 0; + vwEventMask = 0; - if( vClientName.empty() ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME ), vClientName.c_str() ) ); - return MIstatus::failure; - } + if (vClientName.empty()) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str())); + return MIstatus::failure; + } - CMIUtilString strId( vBroadcasterClass.c_str() ); - strId += vClientName; + CMIUtilString strId(vBroadcasterClass.c_str()); + strId += vClientName; - const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find( strId ); - if( it != m_mapIdToEventMask.end() ) - { - vwEventMask = (*it).second; - } + const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId); + if (it != m_mapIdToEventMask.end()) + { + vwEventMask = (*it).second; + } - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERD ), vClientName.c_str() ) ); + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERD), vClientName.c_str())); - return MIstatus::failure; + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Momentarily wait for an events being broadcast and inspect those that do -// come this way. Check if the target should exit event if so start shutting -// down this thread and the application. Any other events pass on to the -// Out-of-band handler to futher determine what kind of event arrived. -// This function runs in the thread "MI debugger event". -// Type: Method. -// Args: vrbIsAlive - (W) False = yes exit event monitoring thread, true = continue. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Momentarily wait for an events being broadcast and inspect those that do +// come this way. Check if the target should exit event if so start shutting +// down this thread and the application. Any other events pass on to the +// Out-of-band handler to futher determine what kind of event arrived. +// This function runs in the thread "MI debugger event". +// Type: Method. +// Args: vrbIsAlive - (W) False = yes exit event monitoring thread, true = continue. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::MonitorSBListenerEvents( bool & vrbIsAlive ) +bool +CMICmnLLDBDebugger::MonitorSBListenerEvents(bool &vrbIsAlive) { - vrbIsAlive = true; - - lldb::SBEvent event; - const bool bGotEvent = m_lldbListener.GetNextEvent( event ); - if ( !bGotEvent || !event.IsValid() ) - { - const std::chrono::milliseconds time( 1 ); - std::this_thread::sleep_for( time ); - return MIstatus::success; - } - if( !event.GetBroadcaster().IsValid() ) - return MIstatus::success; - - // Debugging - m_pLog->WriteLog( CMIUtilString::Format( "##### An event occurred: %s", event.GetBroadcasterClass() ) ); - - bool bHandledEvent = false; - bool bExitAppEvent = false; - const bool bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent( event, bHandledEvent, bExitAppEvent ); - if( !bHandledEvent ) - { - const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT ), event.GetBroadcasterClass() ) ); - m_pLog->WriteLog( msg ); - } - if( !bOk ) - { - m_pLog->WriteLog( CMICmnLLDBDebuggerHandleEvents::Instance().GetErrorDescription() ); - } - - if( bExitAppEvent ) - { - // Set the application to shutdown - m_pClientDriver->SetExitApplicationFlag( true ); - - // Kill *this thread - vrbIsAlive = false; - } - - return bOk; + vrbIsAlive = true; + + lldb::SBEvent event; + const bool bGotEvent = m_lldbListener.GetNextEvent(event); + if (!bGotEvent || !event.IsValid()) + { + const std::chrono::milliseconds time(1); + std::this_thread::sleep_for(time); + return MIstatus::success; + } + if (!event.GetBroadcaster().IsValid()) + return MIstatus::success; + + // Debugging + m_pLog->WriteLog(CMIUtilString::Format("##### An event occurred: %s", event.GetBroadcasterClass())); + + bool bHandledEvent = false; + bool bExitAppEvent = false; + const bool bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent(event, bHandledEvent, bExitAppEvent); + if (!bHandledEvent) + { + const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT), event.GetBroadcasterClass())); + m_pLog->WriteLog(msg); + } + if (!bOk) + { + m_pLog->WriteLog(CMICmnLLDBDebuggerHandleEvents::Instance().GetErrorDescription()); + } + + if (bExitAppEvent) + { + // Set the application to shutdown + m_pClientDriver->SetExitApplicationFlag(true); + + // Kill *this thread + vrbIsAlive = false; + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: The main worker method for this thread. -// Type: Method. -// Args: vrbIsAlive = (W) True = *this thread is working, false = thread has exited. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The main worker method for this thread. +// Type: Method. +// Args: vrbIsAlive - (W) True = *this thread is working, false = thread has exited. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::ThreadRun( bool & vrbIsAlive ) +bool +CMICmnLLDBDebugger::ThreadRun(bool &vrbIsAlive) { - return MonitorSBListenerEvents( vrbIsAlive ); + return MonitorSBListenerEvents(vrbIsAlive); } //++ ------------------------------------------------------------------------------------ -// Details: Let this thread clean up after itself. -// Type: Method. -// Args: -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Let this thread clean up after itself. +// Type: Method. +// Args: +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebugger::ThreadFinish( void ) +bool +CMICmnLLDBDebugger::ThreadFinish(void) { - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve *this thread object's name. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString & - Text. -// Throws: None. +// Details: Retrieve *this thread object's name. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString & - Text. +// Throws: None. //-- -const CMIUtilString & CMICmnLLDBDebugger::ThreadGetName( void ) const +const CMIUtilString & +CMICmnLLDBDebugger::ThreadGetName(void) const { - return m_constStrThisThreadId; + return m_constStrThisThreadId; } diff --git a/tools/lldb-mi/MICmnLLDBDebugger.h b/tools/lldb-mi/MICmnLLDBDebugger.h index 0d608997d959..6075fd85e535 100644 --- a/tools/lldb-mi/MICmnLLDBDebugger.h +++ b/tools/lldb-mi/MICmnLLDBDebugger.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLLDBDebugger.h +// File: MICmnLLDBDebugger.h // -// Overview: CMICmnLLDBDebugger interface. +// Overview: CMICmnLLDBDebugger interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -38,88 +38,84 @@ class CMIDriverBase; class CMICmnLLDBDebuggerHandleEvents; //++ ============================================================================ -// Details: MI proxy/adapter for the LLDB public SBDebugger API. The CMIDriver -// requires *this object. Command classes make calls on *this object -// to facilitate their work effort. The instance runs in its own worker -// thread. -// A singleton class. -// Gotchas: None. -// Authors: Illya Rudkin 26/02/2014. -// Changes: None. +// Details: MI proxy/adapter for the LLDB public SBDebugger API. The CMIDriver +// requires *this object. Command classes make calls on *this object +// to facilitate their work effort. The instance runs in its own worker +// thread. +// A singleton class. +// Gotchas: None. +// Authors: Illya Rudkin 26/02/2014. +// Changes: None. //-- -class CMICmnLLDBDebugger -: public CMICmnBase -, public CMIUtilThreadActiveObjBase -, public MI::ISingleton< CMICmnLLDBDebugger > +class CMICmnLLDBDebugger : public CMICmnBase, public CMIUtilThreadActiveObjBase, public MI::ISingleton { - friend class MI::ISingleton< CMICmnLLDBDebugger >; - -// Methods: -public: - bool Initialize( void ); - bool Shutdown( void ); - - bool SetDriver( const CMIDriverBase & vClientDriver ); - CMIDriverBase & GetDriver( void ) const; - lldb::SBDebugger & GetTheDebugger( void ); - lldb::SBListener & GetTheListener( void ); - - // MI Commands can use these functions to listen for events they require - bool RegisterForEvent( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass, const MIuint vEventMask ); - bool UnregisterForEvent( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass ); - bool RegisterForEvent( const CMIUtilString & vClientName, const lldb::SBBroadcaster & vBroadcaster, const MIuint vEventMask ); - bool UnregisterForEvent( const CMIUtilString & vClientName, const lldb::SBBroadcaster & vBroadcaster ); - -// Overridden: -public: - // From CMIUtilThreadActiveObjBase - virtual const CMIUtilString & ThreadGetName( void ) const; - -// Overridden: -protected: - // From CMIUtilThreadActiveObjBase - virtual bool ThreadRun( bool & vrIsAlive ); - virtual bool ThreadFinish( void ); - -// Typedefs: -private: - typedef std::map< CMIUtilString, MIuint > MapBroadcastClassNameToEventMask_t; - typedef std::pair< CMIUtilString, MIuint > MapPairBroadcastClassNameToEventMask_t; - typedef std::map< CMIUtilString, MIuint > MapIdToEventMask_t; - typedef std::pair< CMIUtilString, MIuint > MapPairIdToEventMask_t; - -// Methods: -private: - /* ctor */ CMICmnLLDBDebugger( void ); - /* ctor */ CMICmnLLDBDebugger( const CMICmnLLDBDebugger & ); - void operator=( const CMICmnLLDBDebugger & ); - - bool InitSBDebugger( void ); - bool InitSBListener( void ); - bool InitStdStreams( void ); - bool MonitorSBListenerEvents( bool & vrbYesExit ); - - bool BroadcasterGetMask( const CMIUtilString & vBroadcasterClass, MIuint & vEventMask ) const; - bool BroadcasterRemoveMask( const CMIUtilString & vBroadcasterClass ); - bool BroadcasterSaveMask( const CMIUtilString & vBroadcasterClass, const MIuint vEventMask ); - - MIuint ClientGetMaskForAllClients( const CMIUtilString & vBroadcasterClass ) const; - bool ClientSaveMask( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass, const MIuint vEventMask ); - bool ClientRemoveTheirMask( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass ); - bool ClientGetTheirMask( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass, MIuint & vwEventMask ); - -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMICmnLLDBDebugger( void ); - -// Attributes: -private: - CMIDriverBase * m_pClientDriver; // The driver that wants to use *this LLDB debugger - lldb::SBDebugger m_lldbDebugger; // SBDebugger is the primordial object that creates SBTargets and provides access to them - lldb::SBListener m_lldbListener; // API clients can register its own listener to debugger events - const CMIUtilString m_constStrThisThreadId; - MapBroadcastClassNameToEventMask_t m_mapBroadcastClassNameToEventMask; - MapIdToEventMask_t m_mapIdToEventMask; -}; + friend class MI::ISingleton; + + // Methods: + public: + bool Initialize(void); + bool Shutdown(void); + + bool SetDriver(const CMIDriverBase &vClientDriver); + CMIDriverBase &GetDriver(void) const; + lldb::SBDebugger &GetTheDebugger(void); + lldb::SBListener &GetTheListener(void); + + // MI Commands can use these functions to listen for events they require + bool RegisterForEvent(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask); + bool UnregisterForEvent(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass); + bool RegisterForEvent(const CMIUtilString &vClientName, const lldb::SBBroadcaster &vBroadcaster, const MIuint vEventMask); + bool UnregisterForEvent(const CMIUtilString &vClientName, const lldb::SBBroadcaster &vBroadcaster); + + // Overridden: + public: + // From CMIUtilThreadActiveObjBase + virtual const CMIUtilString &ThreadGetName(void) const; + + // Overridden: + protected: + // From CMIUtilThreadActiveObjBase + virtual bool ThreadRun(bool &vrIsAlive); + virtual bool ThreadFinish(void); + + // Typedefs: + private: + typedef std::map MapBroadcastClassNameToEventMask_t; + typedef std::pair MapPairBroadcastClassNameToEventMask_t; + typedef std::map MapIdToEventMask_t; + typedef std::pair MapPairIdToEventMask_t; + // Methods: + private: + /* ctor */ CMICmnLLDBDebugger(void); + /* ctor */ CMICmnLLDBDebugger(const CMICmnLLDBDebugger &); + void operator=(const CMICmnLLDBDebugger &); + + bool InitSBDebugger(void); + bool InitSBListener(void); + bool InitStdStreams(void); + bool MonitorSBListenerEvents(bool &vrbYesExit); + + bool BroadcasterGetMask(const CMIUtilString &vBroadcasterClass, MIuint &vEventMask) const; + bool BroadcasterRemoveMask(const CMIUtilString &vBroadcasterClass); + bool BroadcasterSaveMask(const CMIUtilString &vBroadcasterClass, const MIuint vEventMask); + + MIuint ClientGetMaskForAllClients(const CMIUtilString &vBroadcasterClass) const; + bool ClientSaveMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask); + bool ClientRemoveTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass); + bool ClientGetTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask); + + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMICmnLLDBDebugger(void); + + // Attributes: + private: + CMIDriverBase *m_pClientDriver; // The driver that wants to use *this LLDB debugger + lldb::SBDebugger m_lldbDebugger; // SBDebugger is the primordial object that creates SBTargets and provides access to them + lldb::SBListener m_lldbListener; // API clients can register its own listener to debugger events + const CMIUtilString m_constStrThisThreadId; + MapBroadcastClassNameToEventMask_t m_mapBroadcastClassNameToEventMask; + MapIdToEventMask_t m_mapIdToEventMask; +}; diff --git a/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp b/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp index 08218a2e87e4..b375611ec6ec 100644 --- a/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp +++ b/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLLDBDebuggerHandleEvents.cpp +// File: MICmnLLDBDebuggerHandleEvents.cpp // -// Overview: CMICmnLLDBDebuggerHandleEvents implementation. +// Overview: CMICmnLLDBDebuggerHandleEvents implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third party headers: @@ -28,10 +28,10 @@ #include #include #ifdef _WIN32 - #include // For the ::_access() +#include // For the ::_access() #else - #include // For the ::access() -#endif // _WIN32 +#include // For the ::access() +#endif // _WIN32 #include // In-house headers: @@ -49,1518 +49,1559 @@ #include "MIDriver.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBDebuggerHandleEvents constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnLLDBDebuggerHandleEvents constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents( void ) +CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBDebuggerHandleEvents destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnLLDBDebuggerHandleEvents destructor. +// Type: Overridable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents( void ) +CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this broardcaster object. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Initialize resources for *this broardcaster object. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::Initialize( void ) +bool +CMICmnLLDBDebuggerHandleEvents::Initialize(void) { - m_clientUsageRefCnt++; + m_clientUsageRefCnt++; - if( m_bInitialized ) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - m_bInitialized = MIstatus::success; - - return m_bInitialized; + m_bInitialized = MIstatus::success; + + return m_bInitialized; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this broardcaster object. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Release resources for *this broardcaster object. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::Shutdown( void ) +bool +CMICmnLLDBDebuggerHandleEvents::Shutdown(void) { - if( --m_clientUsageRefCnt > 0 ) - return MIstatus::success; - - if( !m_bInitialized ) - return MIstatus::success; + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; + + if (!m_bInitialized) + return MIstatus::success; - m_bInitialized = false; + m_bInitialized = false; - return MIstatus::success; -} + return MIstatus::success; +} //++ ------------------------------------------------------------------------------------ -// Details: Interpret the event object to asscertain the action to take or information to -// to form and put in a MI Out-of-band record object which is given to stdout. -// Type: Method. -// Args: vEvent - (R) An LLDB broadcast event. -// vrbHandledEvent - (W) True - event handled, false = not handled. -// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Interpret the event object to asscertain the action to take or information to +// to form and put in a MI Out-of-band record object which is given to stdout. +// Type: Method. +// Args: vEvent - (R) An LLDB broadcast event. +// vrbHandledEvent - (W) True - event handled, false = not handled. +// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleEvent( const lldb::SBEvent & vEvent, bool & vrbHandledEvent, bool & vrbExitAppEvent ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent, bool &vrbExitAppEvent) { - bool bOk = MIstatus::success; - vrbHandledEvent = false; - vrbExitAppEvent = false; - - if( lldb::SBProcess::EventIsProcessEvent( vEvent ) ) - { - vrbHandledEvent = true; - bOk = HandleEventSBProcess( vEvent, vrbExitAppEvent ); - } - else if( lldb::SBBreakpoint::EventIsBreakpointEvent( vEvent ) ) - { - vrbHandledEvent = true; - bOk = HandleEventSBBreakPoint( vEvent ); - } - else if( lldb::SBThread::EventIsThreadEvent( vEvent ) ) - { - vrbHandledEvent = true; - bOk = HandleEventSBThread( vEvent ); - } - - return bOk; + bool bOk = MIstatus::success; + vrbHandledEvent = false; + vrbExitAppEvent = false; + + if (lldb::SBProcess::EventIsProcessEvent(vEvent)) + { + vrbHandledEvent = true; + bOk = HandleEventSBProcess(vEvent, vrbExitAppEvent); + } + else if (lldb::SBBreakpoint::EventIsBreakpointEvent(vEvent)) + { + vrbHandledEvent = true; + bOk = HandleEventSBBreakPoint(vEvent); + } + else if (lldb::SBThread::EventIsThreadEvent(vEvent)) + { + vrbHandledEvent = true; + bOk = HandleEventSBThread(vEvent); + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Handle a LLDB SBProcess event. -// Type: Method. -// Args: vEvent - (R) An LLDB broadcast event. -// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Handle a LLDB SBProcess event. +// Type: Method. +// Args: vEvent - (R) An LLDB broadcast event. +// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess( const lldb::SBEvent & vEvent, bool & vrbExitAppEvent ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent) { - bool bOk = MIstatus::success; - - const MIchar * pEventType = ""; - const MIuint nEventType = vEvent.GetType(); - switch( nEventType ) - { - case lldb::SBProcess::eBroadcastBitInterrupt: - pEventType = "eBroadcastBitInterrupt"; - break; - case lldb::SBProcess::eBroadcastBitProfileData: - pEventType = "eBroadcastBitProfileData"; - break; - case lldb::SBProcess::eBroadcastBitStateChanged: - pEventType = "eBroadcastBitStateChanged"; - bOk = HandleProcessEventBroadcastBitStateChanged( vEvent, vrbExitAppEvent ); - break; - case lldb::SBProcess::eBroadcastBitSTDERR: - pEventType = "eBroadcastBitSTDERR"; - bOk = GetProcessStderr(); - break; - case lldb::SBProcess::eBroadcastBitSTDOUT: - pEventType = "eBroadcastBitSTDOUT"; - bOk = GetProcessStdout(); - break; - default: - { - const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBProcess", (MIuint) nEventType ) ); - SetErrorDescription( msg ); - return MIstatus::failure; - } - } - m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Process event occurred: %s", pEventType ) ); - - return bOk; + bool bOk = MIstatus::success; + + const MIchar *pEventType = ""; + const MIuint nEventType = vEvent.GetType(); + switch (nEventType) + { + case lldb::SBProcess::eBroadcastBitInterrupt: + pEventType = "eBroadcastBitInterrupt"; + break; + case lldb::SBProcess::eBroadcastBitProfileData: + pEventType = "eBroadcastBitProfileData"; + break; + case lldb::SBProcess::eBroadcastBitStateChanged: + pEventType = "eBroadcastBitStateChanged"; + bOk = HandleProcessEventBroadcastBitStateChanged(vEvent, vrbExitAppEvent); + break; + case lldb::SBProcess::eBroadcastBitSTDERR: + pEventType = "eBroadcastBitSTDERR"; + bOk = GetProcessStderr(); + break; + case lldb::SBProcess::eBroadcastBitSTDOUT: + pEventType = "eBroadcastBitSTDOUT"; + bOk = GetProcessStdout(); + break; + default: + { + const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBProcess", (MIuint)nEventType)); + SetErrorDescription(msg); + return MIstatus::failure; + } + } + m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event occurred: %s", pEventType)); + + return bOk; } - + //++ ------------------------------------------------------------------------------------ -// Details: Handle a LLDB SBBreakpoint event. -// Type: Method. -// Args: vEvent - (R) An LLDB broadcast event. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Handle a LLDB SBBreakpoint event. +// Type: Method. +// Args: vEvent - (R) An LLDB broadcast event. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakPoint( const lldb::SBEvent & vEvent ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakPoint(const lldb::SBEvent &vEvent) { - bool bOk = MIstatus::success; - - const MIchar * pEventType =""; - const lldb::BreakpointEventType eEvent = lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent( vEvent ); - switch( eEvent ) - { - case lldb::eBreakpointEventTypeThreadChanged: - pEventType = "eBreakpointEventTypeThreadChanged"; - break; - case lldb::eBreakpointEventTypeLocationsRemoved: - pEventType = "eBreakpointEventTypeLocationsRemoved"; - break; - case lldb::eBreakpointEventTypeInvalidType: - pEventType = "eBreakpointEventTypeInvalidType"; - break; - case lldb::eBreakpointEventTypeLocationsAdded: - pEventType = "eBreakpointEventTypeLocationsAdded"; - bOk = HandleEventSBBreakpointLocationsAdded( vEvent ); - break; - case lldb::eBreakpointEventTypeAdded: - pEventType = "eBreakpointEventTypeAdded"; - bOk = HandleEventSBBreakpointAdded( vEvent ); - break; - case lldb::eBreakpointEventTypeRemoved: - pEventType = "eBreakpointEventTypeRemoved"; - bOk = HandleEventSBBreakpointCmn( vEvent ); - break; - case lldb::eBreakpointEventTypeLocationsResolved: - pEventType = "eBreakpointEventTypeLocationsResolved"; - break; - case lldb::eBreakpointEventTypeEnabled: - pEventType ="eBreakpointEventTypeEnabled"; - bOk = HandleEventSBBreakpointCmn( vEvent ); - break; - case lldb::eBreakpointEventTypeDisabled: - pEventType = "eBreakpointEventTypeDisabled"; - bOk = HandleEventSBBreakpointCmn( vEvent ); - break; - case lldb::eBreakpointEventTypeCommandChanged: - pEventType = "eBreakpointEventTypeCommandChanged"; - bOk = HandleEventSBBreakpointCmn( vEvent ); - break; - case lldb::eBreakpointEventTypeConditionChanged: - pEventType ="eBreakpointEventTypeConditionChanged"; - bOk = HandleEventSBBreakpointCmn( vEvent ); - break; - case lldb::eBreakpointEventTypeIgnoreChanged: - pEventType = "eBreakpointEventTypeIgnoreChanged"; - bOk = HandleEventSBBreakpointCmn( vEvent ); - break; - default: - { - const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBBreakPoint", (MIuint) eEvent ) ); - SetErrorDescription( msg ); - return MIstatus::failure; - } - } - m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Breakpoint event occurred: %s", pEventType ) ); - - return bOk; + bool bOk = MIstatus::success; + + const MIchar *pEventType = ""; + const lldb::BreakpointEventType eEvent = lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent(vEvent); + switch (eEvent) + { + case lldb::eBreakpointEventTypeThreadChanged: + pEventType = "eBreakpointEventTypeThreadChanged"; + break; + case lldb::eBreakpointEventTypeLocationsRemoved: + pEventType = "eBreakpointEventTypeLocationsRemoved"; + break; + case lldb::eBreakpointEventTypeInvalidType: + pEventType = "eBreakpointEventTypeInvalidType"; + break; + case lldb::eBreakpointEventTypeLocationsAdded: + pEventType = "eBreakpointEventTypeLocationsAdded"; + bOk = HandleEventSBBreakpointLocationsAdded(vEvent); + break; + case lldb::eBreakpointEventTypeAdded: + pEventType = "eBreakpointEventTypeAdded"; + bOk = HandleEventSBBreakpointAdded(vEvent); + break; + case lldb::eBreakpointEventTypeRemoved: + pEventType = "eBreakpointEventTypeRemoved"; + bOk = HandleEventSBBreakpointCmn(vEvent); + break; + case lldb::eBreakpointEventTypeLocationsResolved: + pEventType = "eBreakpointEventTypeLocationsResolved"; + break; + case lldb::eBreakpointEventTypeEnabled: + pEventType = "eBreakpointEventTypeEnabled"; + bOk = HandleEventSBBreakpointCmn(vEvent); + break; + case lldb::eBreakpointEventTypeDisabled: + pEventType = "eBreakpointEventTypeDisabled"; + bOk = HandleEventSBBreakpointCmn(vEvent); + break; + case lldb::eBreakpointEventTypeCommandChanged: + pEventType = "eBreakpointEventTypeCommandChanged"; + bOk = HandleEventSBBreakpointCmn(vEvent); + break; + case lldb::eBreakpointEventTypeConditionChanged: + pEventType = "eBreakpointEventTypeConditionChanged"; + bOk = HandleEventSBBreakpointCmn(vEvent); + break; + case lldb::eBreakpointEventTypeIgnoreChanged: + pEventType = "eBreakpointEventTypeIgnoreChanged"; + bOk = HandleEventSBBreakpointCmn(vEvent); + break; + } + m_pLog->WriteLog(CMIUtilString::Format("##### An SB Breakpoint event occurred: %s", pEventType)); + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Handle a LLDB SBBreakpoint event. -// Type: Method. -// Args: vEvent - (R) An LLDB broadcast event. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Handle a LLDB SBBreakpoint event. +// Type: Method. +// Args: vEvent - (R) An LLDB broadcast event. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointLocationsAdded( const lldb::SBEvent & vEvent ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointLocationsAdded(const lldb::SBEvent &vEvent) { - const MIuint nLoc = lldb::SBBreakpoint::GetNumBreakpointLocationsFromEvent( vEvent ); - if( nLoc == 0 ) - return MIstatus::success; - - lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent( vEvent ); - const CMIUtilString plural( (nLoc == 1) ? "" : "s" ); - const CMIUtilString msg( CMIUtilString::Format( "%d location%s added to breakpoint %d", nLoc, plural.c_str(), brkPt.GetID() ) ); - - return TextToStdout( msg ); + const MIuint nLoc = lldb::SBBreakpoint::GetNumBreakpointLocationsFromEvent(vEvent); + if (nLoc == 0) + return MIstatus::success; + + lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent); + const CMIUtilString plural((nLoc == 1) ? "" : "s"); + const CMIUtilString msg(CMIUtilString::Format("%d location%s added to breakpoint %d", nLoc, plural.c_str(), brkPt.GetID())); + + return TextToStdout(msg); } - + //++ ------------------------------------------------------------------------------------ -// Details: Handle a LLDB SBBreakpoint event. -// Type: Method. -// Args: vEvent - (R) An LLDB broadcast event. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Handle a LLDB SBBreakpoint event. +// Type: Method. +// Args: vEvent - (R) An LLDB broadcast event. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn( const lldb::SBEvent & vEvent ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn(const lldb::SBEvent &vEvent) { - lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent( vEvent ); - if( !brkPt.IsValid() ) - return MIstatus::success; - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; - if( !rSessionInfo.GetBrkPtInfo( brkPt, sBrkPtInfo ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET ), "HandleEventSBBreakpointCmn()", brkPt.GetID() ) ); - return MIstatus::failure; - } - - // CODETAG_LLDB_BREAKPOINT_CREATION - // This is in a worker thread - // Add more breakpoint information or overwrite existing information - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec; - if( !rSessionInfo.RecordBrkPtInfoGet( brkPt.GetID(), sBrkPtInfoRec ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND ), "HandleEventSBBreakpointCmn()", brkPt.GetID() ) ); - return MIstatus::failure; - } - sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp; - sBrkPtInfo.m_bEnabled = brkPt.IsEnabled(); - sBrkPtInfo.m_bHaveArgOptionThreadGrp = false; - sBrkPtInfo.m_strOptThrdGrp = ""; - sBrkPtInfo.m_nTimes = brkPt.GetHitCount(); - sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc; - sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore; - sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending; - sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition; - sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition; - sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId; - sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId; - - // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\", func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" - CMICmnMIValueTuple miValueTuple; - if( !rSessionInfo.MIResponseFormBrkPtInfo( sBrkPtInfo, miValueTuple ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ), "HandleEventSBBreakpointCmn()" ) ); - return MIstatus::failure; - } - - const CMICmnMIValueResult miValueResultC( "bkpt", miValueTuple ); - const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResultC ); - const bool bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord ); - - return bOk; + lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent); + if (!brkPt.IsValid()) + return MIstatus::success; + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; + if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo)) + { + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), "HandleEventSBBreakpointCmn()", brkPt.GetID())); + return MIstatus::failure; + } + + // CODETAG_LLDB_BREAKPOINT_CREATION + // This is in a worker thread + // Add more breakpoint information or overwrite existing information + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec; + if (!rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec)) + { + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND), "HandleEventSBBreakpointCmn()", brkPt.GetID())); + return MIstatus::failure; + } + sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp; + sBrkPtInfo.m_bEnabled = brkPt.IsEnabled(); + sBrkPtInfo.m_bHaveArgOptionThreadGrp = false; + sBrkPtInfo.m_strOptThrdGrp = ""; + sBrkPtInfo.m_nTimes = brkPt.GetHitCount(); + sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc; + sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore; + sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending; + sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition; + sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition; + sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId; + sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId; + + // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\", + // func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" + CMICmnMIValueTuple miValueTuple; + if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple)) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "HandleEventSBBreakpointCmn()")); + return MIstatus::failure; + } + + const CMICmnMIValueResult miValueResultC("bkpt", miValueTuple); + const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResultC); + const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Handle a LLDB SBBreakpoint added event. -// Add more breakpoint information or overwrite existing information. -// Normally a break point session info objects exists by now when an MI command -// was issued to insert a break so the retrieval would normally always succeed -// however should a user type "b main" into a console then LLDB will create a -// breakpoint directly, hence no MI command, hence no previous record of the -// breakpoint so RecordBrkPtInfoGet() will fail. We still get the event though -// so need to create a breakpoint info object here and send appropriate MI -// response. -// Type: Method. -// Args: vEvent - (R) An LLDB broadcast event. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Handle a LLDB SBBreakpoint added event. +// Add more breakpoint information or overwrite existing information. +// Normally a break point session info objects exists by now when an MI command +// was issued to insert a break so the retrieval would normally always succeed +// however should a user type "b main" into a console then LLDB will create a +// breakpoint directly, hence no MI command, hence no previous record of the +// breakpoint so RecordBrkPtInfoGet() will fail. We still get the event though +// so need to create a breakpoint info object here and send appropriate MI +// response. +// Type: Method. +// Args: vEvent - (R) An LLDB broadcast event. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded( const lldb::SBEvent & vEvent ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded(const lldb::SBEvent &vEvent) { - lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent( vEvent ); - if( !brkPt.IsValid() ) - return MIstatus::success; - - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; - if( !rSessionInfo.GetBrkPtInfo( brkPt, sBrkPtInfo ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET ), "HandleEventSBBreakpointAdded()", brkPt.GetID() ) ); - return MIstatus::failure; - } - - // CODETAG_LLDB_BREAKPOINT_CREATION - // This is in a worker thread - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec; - const bool bBrkPtExistAlready = rSessionInfo.RecordBrkPtInfoGet( brkPt.GetID(), sBrkPtInfoRec ); - if( bBrkPtExistAlready ) - { - // Update breakpoint information object - sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp; - sBrkPtInfo.m_bEnabled = brkPt.IsEnabled(); - sBrkPtInfo.m_bHaveArgOptionThreadGrp = false; - sBrkPtInfo.m_strOptThrdGrp.clear(); - sBrkPtInfo.m_nTimes = brkPt.GetHitCount(); - sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc; - sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore; - sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending; - sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition; - sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition; - sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId; - sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId; - } - else - { - // Create a breakpoint information object - sBrkPtInfo.m_bDisp = brkPt.IsOneShot(); - sBrkPtInfo.m_bEnabled = brkPt.IsEnabled(); - sBrkPtInfo.m_bHaveArgOptionThreadGrp = false; - sBrkPtInfo.m_strOptThrdGrp.clear(); - sBrkPtInfo.m_strOrigLoc = CMIUtilString::Format( "%s:%d", sBrkPtInfo.m_fileName.c_str(), sBrkPtInfo.m_nLine ); - sBrkPtInfo.m_nIgnore = brkPt.GetIgnoreCount(); - sBrkPtInfo.m_bPending = false; - const MIchar * pStrCondition = brkPt.GetCondition(); - sBrkPtInfo.m_bCondition = (pStrCondition != nullptr) ? true : false; - sBrkPtInfo.m_strCondition = (pStrCondition != nullptr) ? pStrCondition : "??"; - sBrkPtInfo.m_bBrkPtThreadId = (brkPt.GetThreadID() != 0) ? true : false; - sBrkPtInfo.m_nBrkPtThreadId = brkPt.GetThreadID(); - } - - CMICmnMIValueTuple miValueTuple; - if( !rSessionInfo.MIResponseFormBrkPtInfo( sBrkPtInfo, miValueTuple ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ), "HandleEventSBBreakpointAdded()" ) ); - return MIstatus::failure; - } - - bool bOk = MIstatus::success; - if( bBrkPtExistAlready ) - { - // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" - const CMICmnMIValueResult miValueResult( "bkpt", miValueTuple ); - const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult ); - bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord ); - } - else - { - // CODETAG_LLDB_BRKPT_ID_MAX - if( brkPt.GetID() > (lldb::break_id_t) rSessionInfo.m_nBrkPointCntMax ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_CNT_EXCEEDED ), "HandleEventSBBreakpointAdded()", rSessionInfo.m_nBrkPointCntMax, sBrkPtInfo.m_id ) ); - return MIstatus::failure; - } - if( !rSessionInfo.RecordBrkPtInfo( brkPt.GetID(), sBrkPtInfo ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET ), "HandleEventSBBreakpointAdded()", sBrkPtInfo.m_id ) ); - return MIstatus::failure; - } - - // MI print "=breakpoint-created,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" - const CMICmnMIValueResult miValueResult( "bkpt", miValueTuple ); - const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, miValueResult ); - bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord ); - } - - return bOk; + lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent); + if (!brkPt.IsValid()) + return MIstatus::success; + + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; + if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo)) + { + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), "HandleEventSBBreakpointAdded()", brkPt.GetID())); + return MIstatus::failure; + } + + // CODETAG_LLDB_BREAKPOINT_CREATION + // This is in a worker thread + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec; + const bool bBrkPtExistAlready = rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec); + if (bBrkPtExistAlready) + { + // Update breakpoint information object + sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp; + sBrkPtInfo.m_bEnabled = brkPt.IsEnabled(); + sBrkPtInfo.m_bHaveArgOptionThreadGrp = false; + sBrkPtInfo.m_strOptThrdGrp.clear(); + sBrkPtInfo.m_nTimes = brkPt.GetHitCount(); + sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc; + sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore; + sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending; + sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition; + sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition; + sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId; + sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId; + } + else + { + // Create a breakpoint information object + sBrkPtInfo.m_bDisp = brkPt.IsOneShot(); + sBrkPtInfo.m_bEnabled = brkPt.IsEnabled(); + sBrkPtInfo.m_bHaveArgOptionThreadGrp = false; + sBrkPtInfo.m_strOptThrdGrp.clear(); + sBrkPtInfo.m_strOrigLoc = CMIUtilString::Format("%s:%d", sBrkPtInfo.m_fileName.c_str(), sBrkPtInfo.m_nLine); + sBrkPtInfo.m_nIgnore = brkPt.GetIgnoreCount(); + sBrkPtInfo.m_bPending = false; + const MIchar *pStrCondition = brkPt.GetCondition(); + sBrkPtInfo.m_bCondition = (pStrCondition != nullptr) ? true : false; + sBrkPtInfo.m_strCondition = (pStrCondition != nullptr) ? pStrCondition : "??"; + sBrkPtInfo.m_bBrkPtThreadId = (brkPt.GetThreadID() != 0) ? true : false; + sBrkPtInfo.m_nBrkPtThreadId = brkPt.GetThreadID(); + } + + CMICmnMIValueTuple miValueTuple; + if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple)) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "HandleEventSBBreakpointAdded()")); + return MIstatus::failure; + } + + bool bOk = MIstatus::success; + if (bBrkPtExistAlready) + { + // MI print + // "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" + const CMICmnMIValueResult miValueResult("bkpt", miValueTuple); + const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult); + bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + } + else + { + // CODETAG_LLDB_BRKPT_ID_MAX + if (brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), "HandleEventSBBreakpointAdded()", + rSessionInfo.m_nBrkPointCntMax, sBrkPtInfo.m_id)); + return MIstatus::failure; + } + if (!rSessionInfo.RecordBrkPtInfo(brkPt.GetID(), sBrkPtInfo)) + { + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET), "HandleEventSBBreakpointAdded()", sBrkPtInfo.m_id)); + return MIstatus::failure; + } + + // MI print + // "=breakpoint-created,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" + const CMICmnMIValueResult miValueResult("bkpt", miValueTuple); + const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, miValueResult); + bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Handle a LLDB SBThread event. -// Type: Method. -// Args: vEvent - (R) An LLDB broadcast event. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Handle a LLDB SBThread event. +// Type: Method. +// Args: vEvent - (R) An LLDB broadcast event. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThread( const lldb::SBEvent & vEvent ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleEventSBThread(const lldb::SBEvent &vEvent) { - if( !ChkForStateChanges() ) - return MIstatus::failure; + if (!ChkForStateChanges()) + return MIstatus::failure; - bool bOk = MIstatus::success; - const MIchar * pEventType = ""; + bool bOk = MIstatus::success; + const MIchar *pEventType = ""; const MIuint nEventType = vEvent.GetType(); - switch( nEventType ) - { - case lldb::SBThread::eBroadcastBitStackChanged: - pEventType = "eBroadcastBitStackChanged"; - bOk = HandleEventSBThreadBitStackChanged( vEvent ); - break; - case lldb::SBThread::eBroadcastBitThreadSuspended: - pEventType = "eBroadcastBitThreadSuspended"; - bOk = HandleEventSBThreadSuspended( vEvent ); - break; - case lldb::SBThread::eBroadcastBitThreadResumed: - pEventType = "eBroadcastBitThreadResumed"; - break; - case lldb::SBThread::eBroadcastBitSelectedFrameChanged: - pEventType = "eBroadcastBitSelectedFrameChanged"; - break; - case lldb::SBThread::eBroadcastBitThreadSelected: - pEventType = "eBroadcastBitThreadSelected"; - break; - default: - { - const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBThread", (MIuint) nEventType ) ); - SetErrorDescription( msg ); - return MIstatus::failure; - } - } - m_pLog->WriteLog( CMIUtilString::Format( "##### An SBThread event occurred: %s", pEventType ) ); - - return bOk; + switch (nEventType) + { + case lldb::SBThread::eBroadcastBitStackChanged: + pEventType = "eBroadcastBitStackChanged"; + bOk = HandleEventSBThreadBitStackChanged(vEvent); + break; + case lldb::SBThread::eBroadcastBitThreadSuspended: + pEventType = "eBroadcastBitThreadSuspended"; + bOk = HandleEventSBThreadSuspended(vEvent); + break; + case lldb::SBThread::eBroadcastBitThreadResumed: + pEventType = "eBroadcastBitThreadResumed"; + break; + case lldb::SBThread::eBroadcastBitSelectedFrameChanged: + pEventType = "eBroadcastBitSelectedFrameChanged"; + break; + case lldb::SBThread::eBroadcastBitThreadSelected: + pEventType = "eBroadcastBitThreadSelected"; + break; + default: + { + const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBThread", (MIuint)nEventType)); + SetErrorDescription(msg); + return MIstatus::failure; + } + } + m_pLog->WriteLog(CMIUtilString::Format("##### An SBThread event occurred: %s", pEventType)); + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Handle a LLDB SBThread event. -// Type: Method. -// Args: vEvent - (R) An LLDB broadcast event. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Handle a LLDB SBThread event. +// Type: Method. +// Args: vEvent - (R) An LLDB broadcast event. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended( const lldb::SBEvent & vEvent ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended(const lldb::SBEvent &vEvent) { - lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent( vEvent ); - if( !thread.IsValid() ) - return MIstatus::success; - - const lldb::StopReason eStopReason = thread.GetStopReason(); - if( eStopReason != lldb::eStopReasonSignal ) - return MIstatus::success; - - // MI print "@thread=%d,signal=%lld" - const MIuint64 nId = thread.GetStopReasonDataAtIndex( 0 ); - const CMIUtilString strThread( CMIUtilString::Format( "%d", thread.GetThreadID() ) ); - const CMICmnMIValueConst miValueConst( strThread ); - const CMICmnMIValueResult miValueResult( "thread", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Thread, miValueResult ); - const CMIUtilString strSignal( CMIUtilString::Format( "%lld", nId ) ); - const CMICmnMIValueConst miValueConst2( strSignal ); - const CMICmnMIValueResult miValueResult2( "signal", miValueConst2 ); - bool bOk = miOutOfBandRecord.Add( miValueResult2 ); - bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord ); - - return bOk; + lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent); + if (!thread.IsValid()) + return MIstatus::success; + + const lldb::StopReason eStopReason = thread.GetStopReason(); + if (eStopReason != lldb::eStopReasonSignal) + return MIstatus::success; + + // MI print "@thread=%d,signal=%lld" + const MIuint64 nId = thread.GetStopReasonDataAtIndex(0); + const CMIUtilString strThread(CMIUtilString::Format("%d", thread.GetThreadID())); + const CMICmnMIValueConst miValueConst(strThread); + const CMICmnMIValueResult miValueResult("thread", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Thread, miValueResult); + const CMIUtilString strSignal(CMIUtilString::Format("%lld", nId)); + const CMICmnMIValueConst miValueConst2(strSignal); + const CMICmnMIValueResult miValueResult2("signal", miValueConst2); + bool bOk = miOutOfBandRecord.Add(miValueResult2); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Handle a LLDB SBThread event. -// Type: Method. -// Args: vEvent - (R) An LLDB broadcast event. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Handle a LLDB SBThread event. +// Type: Method. +// Args: vEvent - (R) An LLDB broadcast event. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged( const lldb::SBEvent & vEvent ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged(const lldb::SBEvent &vEvent) { - lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent( vEvent ); - if( !thread.IsValid() ) - return MIstatus::success; + lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent); + if (!thread.IsValid()) + return MIstatus::success; - lldb::SBStream streamOut; - const bool bOk = thread.GetStatus( streamOut ); - return bOk && TextToStdout( streamOut.GetData() ); + lldb::SBStream streamOut; + const bool bOk = thread.GetStatus(streamOut); + return bOk && TextToStdout(streamOut.GetData()); } - + //++ ------------------------------------------------------------------------------------ -// Details: Handle a LLDB SBCommandInterpreter event. -// Type: Method. -// Args: vEvent - (R) An LLDB command interpreter event. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Handle a LLDB SBCommandInterpreter event. +// Type: Method. +// Args: vEvent - (R) An LLDB command interpreter event. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter( const lldb::SBEvent & vEvent ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter(const lldb::SBEvent &vEvent) { - // This function is not used - // *** This function is under development + // This function is not used + // *** This function is under development - const MIchar * pEventType = ""; + const MIchar *pEventType = ""; const MIuint nEventType = vEvent.GetType(); - switch( nEventType ) - { - case lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit: - pEventType ="eBroadcastBitThreadShouldExit"; - // ToDo: IOR: Reminder to maybe handle this here - //const MIuint nEventType = event.GetType(); - //if( nEventType & lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit ) - //{ - // m_pClientDriver->SetExitApplicationFlag(); - // vrbYesExit = true; - // return MIstatus::success; - //} break; - case lldb::SBCommandInterpreter::eBroadcastBitResetPrompt: - pEventType = "eBroadcastBitResetPrompt"; - break; - case lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived: - pEventType = "eBroadcastBitQuitCommandReceived"; - break; - case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData: - pEventType = "eBroadcastBitAsynchronousOutputData"; - break; - case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData: - pEventType = "eBroadcastBitAsynchronousErrorData"; - break; - default: - { - const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBCommandInterpreter", (MIuint) nEventType ) ); - SetErrorDescription( msg ); - return MIstatus::failure; - } - } - m_pLog->WriteLog( CMIUtilString::Format( "##### An SBCommandInterpreter event occurred: %s", pEventType ) ); - - return MIstatus::success; + switch (nEventType) + { + case lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit: + pEventType = "eBroadcastBitThreadShouldExit"; + // ToDo: IOR: Reminder to maybe handle this here + // const MIuint nEventType = event.GetType(); + // if (nEventType & lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit) + //{ + // m_pClientDriver->SetExitApplicationFlag(); + // vrbYesExit = true; + // return MIstatus::success; + //} break; + case lldb::SBCommandInterpreter::eBroadcastBitResetPrompt: + pEventType = "eBroadcastBitResetPrompt"; + break; + case lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived: + pEventType = "eBroadcastBitQuitCommandReceived"; + break; + case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData: + pEventType = "eBroadcastBitAsynchronousOutputData"; + break; + case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData: + pEventType = "eBroadcastBitAsynchronousErrorData"; + break; + default: + { + const CMIUtilString msg( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBCommandInterpreter", (MIuint)nEventType)); + SetErrorDescription(msg); + return MIstatus::failure; + } + } + m_pLog->WriteLog(CMIUtilString::Format("##### An SBCommandInterpreter event occurred: %s", pEventType)); + + return MIstatus::success; } - + //++ ------------------------------------------------------------------------------------ -// Details: Handle SBProcess event eBroadcastBitStateChanged. -// Type: Method. -// Args: vEvent - (R) An LLDB event object. -// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Handle SBProcess event eBroadcastBitStateChanged. +// Type: Method. +// Args: vEvent - (R) An LLDB event object. +// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged( const lldb::SBEvent & vEvent, bool & vrbExitAppEvent ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent) { - bool bOk = ChkForStateChanges(); - bOk = bOk && GetProcessStdout(); - bOk = bOk && GetProcessStderr(); - if( !bOk ) - return MIstatus::failure; - - // Something changed in the process; get the event and report the process's current - // status and location - const lldb::StateType eEventState = lldb::SBProcess::GetStateFromEvent( vEvent ); - if( eEventState == lldb::eStateInvalid ) - return MIstatus::success; - - lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent( vEvent ); - if( !process.IsValid() ) - { - const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID ), "SBProcess", "HandleProcessEventBroadcastBitStateChanged()" ) ); - SetErrorDescription( msg ); - return MIstatus::failure; - } - - bool bShouldBrk = true; - const MIchar * pEventType = ""; - switch( eEventState ) - { - case lldb::eStateUnloaded: - pEventType = "eStateUnloaded"; - break; - case lldb::eStateConnected: - pEventType = "eStateConnected"; - break; - case lldb::eStateAttaching: - pEventType = "eStateAttaching"; - break; - case lldb::eStateLaunching: - pEventType ="eStateLaunching"; - break; - case lldb::eStateStopped: - pEventType = "eStateStopped"; - bOk = HandleProcessEventStateStopped( bShouldBrk ); - if( bShouldBrk ) - break; - case lldb::eStateCrashed: - case lldb::eStateSuspended: - pEventType = "eStateSuspended"; - bOk = HandleProcessEventStateSuspended( vEvent ); - break; - case lldb::eStateRunning: - pEventType = "eStateRunning"; - bOk = HandleProcessEventStateRunning(); - break; - case lldb::eStateStepping: - pEventType = "eStateStepping"; - break; - case lldb::eStateDetached: - pEventType = "eStateDetached"; - break; - case lldb::eStateExited: - pEventType = "eStateExited"; - vrbExitAppEvent = true; - bOk = HandleProcessEventStateExited(); - break; - default: - { - const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBProcess BroadcastBitStateChanged", (MIuint) eEventState ) ); - SetErrorDescription( msg ); - return MIstatus::failure; - } - } - - // ToDo: Remove when finished coding application - m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Process event BroadcastBitStateChanged occurred: %s", pEventType ) ); - - return bOk; + bool bOk = ChkForStateChanges(); + bOk = bOk && GetProcessStdout(); + bOk = bOk && GetProcessStderr(); + if (!bOk) + return MIstatus::failure; + + // Something changed in the process; get the event and report the process's current + // status and location + const lldb::StateType eEventState = lldb::SBProcess::GetStateFromEvent(vEvent); + if (eEventState == lldb::eStateInvalid) + return MIstatus::success; + + lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent(vEvent); + if (!process.IsValid()) + { + const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID), "SBProcess", + "HandleProcessEventBroadcastBitStateChanged()")); + SetErrorDescription(msg); + return MIstatus::failure; + } + + bool bShouldBrk = true; + const MIchar *pEventType = ""; + switch (eEventState) + { + case lldb::eStateUnloaded: + pEventType = "eStateUnloaded"; + break; + case lldb::eStateConnected: + pEventType = "eStateConnected"; + break; + case lldb::eStateAttaching: + pEventType = "eStateAttaching"; + break; + case lldb::eStateLaunching: + pEventType = "eStateLaunching"; + break; + case lldb::eStateStopped: + pEventType = "eStateStopped"; + bOk = HandleProcessEventStateStopped(bShouldBrk); + if (bShouldBrk) + break; + case lldb::eStateCrashed: + case lldb::eStateSuspended: + pEventType = "eStateSuspended"; + bOk = HandleProcessEventStateSuspended(vEvent); + break; + case lldb::eStateRunning: + pEventType = "eStateRunning"; + bOk = HandleProcessEventStateRunning(); + break; + case lldb::eStateStepping: + pEventType = "eStateStepping"; + break; + case lldb::eStateDetached: + pEventType = "eStateDetached"; + break; + case lldb::eStateExited: + pEventType = "eStateExited"; + vrbExitAppEvent = true; + bOk = HandleProcessEventStateExited(); + break; + default: + { + const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBProcess BroadcastBitStateChanged", + (MIuint)eEventState)); + SetErrorDescription(msg); + return MIstatus::failure; + } + } + + // ToDo: Remove when finished coding application + m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event BroadcastBitStateChanged occurred: %s", pEventType)); + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Asynchronous event handler for LLDB Process state suspended. -// Type: Method. -// Args: vEvent - (R) An LLDB event object. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Asynchronous event handler for LLDB Process state suspended. +// Type: Method. +// Args: vEvent - (R) An LLDB event object. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended( const lldb::SBEvent & vEvent ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended(const lldb::SBEvent &vEvent) { - // Make sure the program hasn't been auto-restarted: - if( lldb::SBProcess::GetRestartedFromEvent( vEvent ) ) - return MIstatus::success; - - bool bOk = MIstatus::success; - lldb::SBDebugger & rDebugger = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger; - lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - lldb::SBTarget target = rProcess.GetTarget(); - if( rDebugger.GetSelectedTarget() == target ) - { - if( !UpdateSelectedThread() ) - return MIstatus::failure; - - lldb::SBCommandReturnObject result; - const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand( "process status", result, false ); MIunused( status ); - bOk = TextToStderr( result.GetError() ); - bOk = bOk && TextToStdout( result.GetOutput() ); - } - else - { - lldb::SBStream streamOut; - const MIuint nTargetIndex = rDebugger.GetIndexOfTarget( target ); - if( nTargetIndex != UINT_MAX ) - streamOut.Printf( "Target %d: (", nTargetIndex ); - else - streamOut.Printf( "Target : (" ); - target.GetDescription( streamOut, lldb::eDescriptionLevelBrief ); - streamOut.Printf( ") stopped.\n" ); - bOk = TextToStdout( streamOut.GetData() ); - } - - return bOk; + // Make sure the program hasn't been auto-restarted: + if (lldb::SBProcess::GetRestartedFromEvent(vEvent)) + return MIstatus::success; + + bool bOk = MIstatus::success; + lldb::SBDebugger &rDebugger = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger; + lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; + lldb::SBTarget target = rProcess.GetTarget(); + if (rDebugger.GetSelectedTarget() == target) + { + if (!UpdateSelectedThread()) + return MIstatus::failure; + + lldb::SBCommandReturnObject result; + const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand("process status", result, false); + MIunused(status); + bOk = TextToStderr(result.GetError()); + bOk = bOk && TextToStdout(result.GetOutput()); + } + else + { + lldb::SBStream streamOut; + const MIuint nTargetIndex = rDebugger.GetIndexOfTarget(target); + if (nTargetIndex != UINT_MAX) + streamOut.Printf("Target %d: (", nTargetIndex); + else + streamOut.Printf("Target : ("); + target.GetDescription(streamOut, lldb::eDescriptionLevelBrief); + streamOut.Printf(") stopped.\n"); + bOk = TextToStdout(streamOut.GetData()); + } + + return bOk; } - + //++ ------------------------------------------------------------------------------------ -// Details: Print to stdout MI formatted text to indicate process stopped. -// Type: Method. -// Args: vwrbShouldBrk - (W) True = Yes break, false = do not. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Print to stdout MI formatted text to indicate process stopped. +// Type: Method. +// Args: vwrbShouldBrk - (W) True = Yes break, false = do not. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped( bool & vwrbShouldBrk ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped(bool &vwrbShouldBrk) { - if( !UpdateSelectedThread() ) - return MIstatus::failure; - - const MIchar * pEventType = ""; - bool bOk = MIstatus::success; - lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - const lldb::StopReason eStoppedReason = rProcess.GetSelectedThread().GetStopReason(); - switch( eStoppedReason ) - { - case lldb::eStopReasonInvalid: - pEventType = "eStopReasonInvalid"; - vwrbShouldBrk = false; - break; - case lldb::eStopReasonNone: - pEventType = "eStopReasonNone"; - break; - case lldb::eStopReasonTrace: - pEventType = "eStopReasonTrace"; - bOk = HandleProcessEventStopReasonTrace(); - break; - case lldb::eStopReasonBreakpoint: - pEventType = "eStopReasonBreakpoint"; - bOk = HandleProcessEventStopReasonBreakpoint(); - break; - case lldb::eStopReasonWatchpoint: - pEventType = "eStopReasonWatchpoint"; - break; - case lldb::eStopReasonSignal: - pEventType = "eStopReasonSignal"; - bOk = HandleProcessEventStopSignal( vwrbShouldBrk ); - break; - case lldb::eStopReasonException: - pEventType ="eStopReasonException"; - break; - case lldb::eStopReasonExec: - pEventType = "eStopReasonExec"; - break; - case lldb::eStopReasonPlanComplete: - pEventType = "eStopReasonPlanComplete"; - bOk = HandleProcessEventStopReasonTrace(); - break; - case lldb::eStopReasonThreadExiting: - pEventType = "eStopReasonThreadExiting"; - break; - default: - { - vwrbShouldBrk = false; - - // MI print "*stopped,reason=\"%d\",stopped-threads=\"all\",from-thread=\"%u\"" - const CMIUtilString strReason( CMIUtilString::Format( "%d", eStoppedReason ) ); - const CMICmnMIValueConst miValueConst( strReason ); - const CMICmnMIValueResult miValueResult( "reason", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult ); - const CMICmnMIValueConst miValueConst2( "all" ); - const CMICmnMIValueResult miValueResult2( "stopped-threads", miValueConst2 ); - bOk = miOutOfBandRecord.Add( miValueResult2 ); - const CMIUtilString strFromThread( CMIUtilString::Format( "%u", rProcess.GetSelectedThread().GetIndexID() ) ); - const CMICmnMIValueConst miValueConst3( strFromThread ); - const CMICmnMIValueResult miValueResult3( "from-thread", miValueConst3 ); - bOk = bOk && miOutOfBandRecord.Add( miValueResult3 ); - bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord ); - bOk = bOk && TextToStdout( "(gdb)" ); - } - } - - // ToDo: Remove when finished coding application - m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Process event stop state occurred: %s", pEventType ) ); - - return bOk; + if (!UpdateSelectedThread()) + return MIstatus::failure; + + const MIchar *pEventType = ""; + bool bOk = MIstatus::success; + lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; + const lldb::StopReason eStoppedReason = rProcess.GetSelectedThread().GetStopReason(); + switch (eStoppedReason) + { + case lldb::eStopReasonInvalid: + pEventType = "eStopReasonInvalid"; + vwrbShouldBrk = false; + break; + case lldb::eStopReasonNone: + pEventType = "eStopReasonNone"; + break; + case lldb::eStopReasonTrace: + pEventType = "eStopReasonTrace"; + bOk = HandleProcessEventStopReasonTrace(); + break; + case lldb::eStopReasonBreakpoint: + pEventType = "eStopReasonBreakpoint"; + bOk = HandleProcessEventStopReasonBreakpoint(); + break; + case lldb::eStopReasonWatchpoint: + pEventType = "eStopReasonWatchpoint"; + break; + case lldb::eStopReasonSignal: + pEventType = "eStopReasonSignal"; + bOk = HandleProcessEventStopSignal(vwrbShouldBrk); + break; + case lldb::eStopReasonException: + pEventType = "eStopReasonException"; + break; + case lldb::eStopReasonExec: + pEventType = "eStopReasonExec"; + break; + case lldb::eStopReasonPlanComplete: + pEventType = "eStopReasonPlanComplete"; + bOk = HandleProcessEventStopReasonTrace(); + break; + case lldb::eStopReasonThreadExiting: + pEventType = "eStopReasonThreadExiting"; + break; + } + + // ToDo: Remove when finished coding application + m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event stop state occurred: %s", pEventType)); + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Asynchronous event handler for LLDB Process stop signal. -// Type: Method. -// Args: vwrbShouldBrk - (W) True = Yes break, false = do not. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Asynchronous event handler for LLDB Process stop signal. +// Type: Method. +// Args: vwrbShouldBrk - (W) True = Yes break, false = do not. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal( bool & vwrbShouldBrk ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(bool &vwrbShouldBrk) { - bool bOk = MIstatus::success; - - lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - const MIuint64 nStopReason = rProcess.GetSelectedThread().GetStopReasonDataAtIndex( 0 ); - switch( nStopReason ) - { - case 2: // Terminal interrupt signal. SIGINT - { - // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGNINT\",signal-meaning=\"Interrupt\",frame={%s}" - const CMICmnMIValueConst miValueConst( "signal-received" ); - const CMICmnMIValueResult miValueResult( "reason", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult ); - const CMICmnMIValueConst miValueConst2( "SIGINT" ); - const CMICmnMIValueResult miValueResult2( "signal-name", miValueConst2 ); - bOk = miOutOfBandRecord.Add( miValueResult2 ); - const CMICmnMIValueConst miValueConst3( "Interrupt" ); - const CMICmnMIValueResult miValueResult3( "signal-meaning", miValueConst3 ); - bOk = bOk && miOutOfBandRecord.Add( miValueResult3 ); - CMICmnMIValueTuple miValueTuple; - bOk = bOk && MiHelpGetCurrentThreadFrame( miValueTuple ); - const CMICmnMIValueResult miValueResult5( "frame", miValueTuple ); - bOk = bOk && miOutOfBandRecord.Add( miValueResult5 ); - bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord ); - bOk = bOk && TextToStdout( "(gdb)" ); - } - break; - case 11: // Invalid memory reference. SIGSEGV - { - // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGSEGV\",signal-meaning=\"Segmentation fault\",thread-id=\"%d\",frame={%s}" - const CMICmnMIValueConst miValueConst( "signal-received" ); - const CMICmnMIValueResult miValueResult( "reason", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult ); - const CMICmnMIValueConst miValueConst2( "SIGSEGV" ); - const CMICmnMIValueResult miValueResult2( "signal-name", miValueConst2 ); - bOk = miOutOfBandRecord.Add( miValueResult2 ); - const CMICmnMIValueConst miValueConst3( "Segmentation fault" ); - const CMICmnMIValueResult miValueResult3( "signal-meaning", miValueConst3 ); - bOk = bOk && miOutOfBandRecord.Add( miValueResult3 ); - const CMIUtilString strThreadId( CMIUtilString::Format( "%d", rProcess.GetSelectedThread().GetIndexID() ) ); - const CMICmnMIValueConst miValueConst4( strThreadId ); - const CMICmnMIValueResult miValueResult4( "thread-id", miValueConst4 ); - bOk = bOk && miOutOfBandRecord.Add( miValueResult4 ); - CMICmnMIValueTuple miValueTuple; - bOk = bOk && MiHelpGetCurrentThreadFrame( miValueTuple ); - const CMICmnMIValueResult miValueResult5( "frame", miValueTuple ); - bOk = bOk && miOutOfBandRecord.Add( miValueResult5 ); - bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord ); - // Note no "(gdb)" output here - } - break; - case 19: - if( rProcess.IsValid() ) - rProcess.Continue(); - break; - case 5: // Trace/breakpoint trap. SIGTRAP - { - lldb::SBThread thread = rProcess.GetSelectedThread(); - const MIuint nFrames = thread.GetNumFrames(); - if( nFrames > 0 ) - { - lldb::SBFrame frame = thread.GetFrameAtIndex( 0 ); - const char * pFnName = frame.GetFunctionName(); - if( pFnName != nullptr ) - { - const CMIUtilString fnName = CMIUtilString( pFnName ); - static const CMIUtilString threadCloneFn = CMIUtilString( "__pthread_clone" ); - - if( CMIUtilString::Compare( threadCloneFn, fnName ) ) - { - if( rProcess.IsValid() ) - { - rProcess.Continue(); - vwrbShouldBrk = true; - break; - } - } - } - } - } - default: - { - // MI print "*stopped,reason=\"signal-received\",signal=\"%lld\",stopped-threads=\"all\"" - const CMICmnMIValueConst miValueConst( "signal-received" ); - const CMICmnMIValueResult miValueResult( "reason", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult ); - const CMIUtilString strReason( CMIUtilString::Format( "%lld", nStopReason ) ); - const CMICmnMIValueConst miValueConst2( strReason ); - const CMICmnMIValueResult miValueResult2( "signal", miValueConst2 ); - bOk = miOutOfBandRecord.Add( miValueResult2 ); - const CMICmnMIValueConst miValueConst3( "all" ); - const CMICmnMIValueResult miValueResult3( "stopped-threads", miValueConst3 ); - bOk = bOk && miOutOfBandRecord.Add( miValueResult3 ); - bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord ); - bOk = bOk && TextToStdout( "(gdb)" ); - } - } // switch( nStopReason ) - - return bOk; + bool bOk = MIstatus::success; + + lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; + const MIuint64 nStopReason = rProcess.GetSelectedThread().GetStopReasonDataAtIndex(0); + switch (nStopReason) + { + case 2: // Terminal interrupt signal. SIGINT + { + // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGNINT\",signal-meaning=\"Interrupt\",frame={%s}" + const CMICmnMIValueConst miValueConst("signal-received"); + const CMICmnMIValueResult miValueResult("reason", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + const CMICmnMIValueConst miValueConst2("SIGINT"); + const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2); + bOk = miOutOfBandRecord.Add(miValueResult2); + const CMICmnMIValueConst miValueConst3("Interrupt"); + const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3); + bOk = bOk && miOutOfBandRecord.Add(miValueResult3); + CMICmnMIValueTuple miValueTuple; + bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple); + const CMICmnMIValueResult miValueResult5("frame", miValueTuple); + bOk = bOk && miOutOfBandRecord.Add(miValueResult5); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && TextToStdout("(gdb)"); + } + break; + case 11: // Invalid memory reference. SIGSEGV + { + // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGSEGV\",signal-meaning=\"Segmentation + // fault\",thread-id=\"%d\",frame={%s}" + const CMICmnMIValueConst miValueConst("signal-received"); + const CMICmnMIValueResult miValueResult("reason", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + const CMICmnMIValueConst miValueConst2("SIGSEGV"); + const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2); + bOk = miOutOfBandRecord.Add(miValueResult2); + const CMICmnMIValueConst miValueConst3("Segmentation fault"); + const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3); + bOk = bOk && miOutOfBandRecord.Add(miValueResult3); + const CMIUtilString strThreadId(CMIUtilString::Format("%d", rProcess.GetSelectedThread().GetIndexID())); + const CMICmnMIValueConst miValueConst4(strThreadId); + const CMICmnMIValueResult miValueResult4("thread-id", miValueConst4); + bOk = bOk && miOutOfBandRecord.Add(miValueResult4); + CMICmnMIValueTuple miValueTuple; + bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple); + const CMICmnMIValueResult miValueResult5("frame", miValueTuple); + bOk = bOk && miOutOfBandRecord.Add(miValueResult5); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); + // Note no "(gdb)" output here + } + break; + case 19: + if (rProcess.IsValid()) + rProcess.Continue(); + break; + case 5: // Trace/breakpoint trap. SIGTRAP + { + lldb::SBThread thread = rProcess.GetSelectedThread(); + const MIuint nFrames = thread.GetNumFrames(); + if (nFrames > 0) + { + lldb::SBFrame frame = thread.GetFrameAtIndex(0); + const char *pFnName = frame.GetFunctionName(); + if (pFnName != nullptr) + { + const CMIUtilString fnName = CMIUtilString(pFnName); + static const CMIUtilString threadCloneFn = CMIUtilString("__pthread_clone"); + + if (CMIUtilString::Compare(threadCloneFn, fnName)) + { + if (rProcess.IsValid()) + { + rProcess.Continue(); + vwrbShouldBrk = true; + break; + } + } + } + } + } + default: + { + // MI print "*stopped,reason=\"signal-received\",signal=\"%lld\",stopped-threads=\"all\"" + const CMICmnMIValueConst miValueConst("signal-received"); + const CMICmnMIValueResult miValueResult("reason", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + const CMIUtilString strReason(CMIUtilString::Format("%lld", nStopReason)); + const CMICmnMIValueConst miValueConst2(strReason); + const CMICmnMIValueResult miValueResult2("signal", miValueConst2); + bOk = miOutOfBandRecord.Add(miValueResult2); + const CMICmnMIValueConst miValueConst3("all"); + const CMICmnMIValueResult miValueResult3("stopped-threads", miValueConst3); + bOk = bOk && miOutOfBandRecord.Add(miValueResult3); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && TextToStdout("(gdb)"); + } + } // switch( nStopReason ) + + return bOk; } - + //++ ------------------------------------------------------------------------------------ -// Details: Form partial MI response in a MI value tuple object. -// Type: Method. -// Args: vwrMiValueTuple - (W) MI value tuple object. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Form partial MI response in a MI value tuple object. +// Type: Method. +// Args: vwrMiValueTuple - (W) MI value tuple object. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame( CMICmnMIValueTuple & vwrMiValueTuple ) +bool +CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple &vwrMiValueTuple) { - CMIUtilString strThreadFrame; - lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - lldb::SBThread thread = rProcess.GetSelectedThread(); - const MIuint nFrame = thread.GetNumFrames(); - if( nFrame == 0 ) - { - // MI print "addr=\"??\",func=\"??\",file=\"??\",fullname=\"??\",line=\"??\"" - const CMICmnMIValueConst miValueConst( "??" ); - const CMICmnMIValueResult miValueResult( "addr", miValueConst ); - CMICmnMIValueTuple miValueTuple( miValueResult ); - const CMICmnMIValueResult miValueResult2( "func", miValueConst ); - miValueTuple.Add( miValueResult2 ); - const CMICmnMIValueResult miValueResult4( "file", miValueConst ); - miValueTuple.Add( miValueResult4 ); - const CMICmnMIValueResult miValueResult5( "fullname", miValueConst ); - miValueTuple.Add( miValueResult5 ); - const CMICmnMIValueResult miValueResult6( "line", miValueConst ); - miValueTuple.Add( miValueResult6 ); - - vwrMiValueTuple = miValueTuple; - - return MIstatus::success; - } - - CMICmnMIValueTuple miValueTuple; - if( !CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo( thread, 0, miValueTuple ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ), "MiHelpGetCurrentThreadFrame()" ) ); - return MIstatus::failure; - } - - vwrMiValueTuple = miValueTuple; - - return MIstatus::success; + CMIUtilString strThreadFrame; + lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; + lldb::SBThread thread = rProcess.GetSelectedThread(); + const MIuint nFrame = thread.GetNumFrames(); + if (nFrame == 0) + { + // MI print "addr=\"??\",func=\"??\",file=\"??\",fullname=\"??\",line=\"??\"" + const CMICmnMIValueConst miValueConst("??"); + const CMICmnMIValueResult miValueResult("addr", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueResult miValueResult2("func", miValueConst); + miValueTuple.Add(miValueResult2); + const CMICmnMIValueResult miValueResult4("file", miValueConst); + miValueTuple.Add(miValueResult4); + const CMICmnMIValueResult miValueResult5("fullname", miValueConst); + miValueTuple.Add(miValueResult5); + const CMICmnMIValueResult miValueResult6("line", miValueConst); + miValueTuple.Add(miValueResult6); + + vwrMiValueTuple = miValueTuple; + + return MIstatus::success; + } + + CMICmnMIValueTuple miValueTuple; + if (!CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo(thread, 0, miValueTuple)) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "MiHelpGetCurrentThreadFrame()")); + return MIstatus::failure; + } + + vwrMiValueTuple = miValueTuple; + + return MIstatus::success; } - + //++ ------------------------------------------------------------------------------------ -// Details: Asynchronous event handler for LLDB Process stop reason breakpoint. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Asynchronous event handler for LLDB Process stop reason breakpoint. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint( void ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint(void) { - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - if( !CMIDriver::Instance().SetDriverStateRunningNotDebugging() ) - { - const CMIUtilString & rErrMsg( CMIDriver::Instance().GetErrorDescription() ); - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE ), "HandleProcessEventStopReasonBreakpoint()", rErrMsg.c_str() ) ); - return MIstatus::failure; - } - - lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - const MIuint64 brkPtId = rProcess.GetSelectedThread().GetStopReasonDataAtIndex( 0 ); - lldb::SBBreakpoint brkPt = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget.GetBreakpointAtIndex( (MIuint) brkPtId ); - - return MiStoppedAtBreakPoint( brkPtId, brkPt ); + // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM + if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging()) + { + const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE), + "HandleProcessEventStopReasonBreakpoint()", rErrMsg.c_str())); + return MIstatus::failure; + } + + lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; + const MIuint64 brkPtId = rProcess.GetSelectedThread().GetStopReasonDataAtIndex(0); + lldb::SBBreakpoint brkPt = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget.GetBreakpointAtIndex((MIuint)brkPtId); + + return MiStoppedAtBreakPoint(brkPtId, brkPt); } //++ ------------------------------------------------------------------------------------ -// Details: Form the MI Out-of-band response for stopped reason on hitting a break point. -// Type: Method. -// Args: vBrkPtId - (R) The LLDB break point's ID -// vBrkPt - (R) THe LLDB break point object. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Form the MI Out-of-band response for stopped reason on hitting a break point. +// Type: Method. +// Args: vBrkPtId - (R) The LLDB break point's ID +// vBrkPt - (R) THe LLDB break point object. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint( const MIuint64 vBrkPtId, const lldb::SBBreakpoint & vBrkPt ) +bool +CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, const lldb::SBBreakpoint &vBrkPt) { - bool bOk = MIstatus::success; - - lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - lldb::SBThread thread = rProcess.GetSelectedThread(); - const MIuint nFrame = thread.GetNumFrames(); - if( nFrame == 0 ) - { - // MI print "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={},thread-id=\"%d\",stopped-threads=\"all\"" - const CMICmnMIValueConst miValueConst( "breakpoint-hit" ); - const CMICmnMIValueResult miValueResult( "reason", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult ); - const CMICmnMIValueConst miValueConst2( "del" ); - const CMICmnMIValueResult miValueResult2( "disp", miValueConst2 ); - bOk = miOutOfBandRecord.Add( miValueResult2 ); - const CMIUtilString strBkp( CMIUtilString::Format( "%d", vBrkPtId ) ); - const CMICmnMIValueConst miValueConst3( strBkp ); - CMICmnMIValueResult miValueResult3( "bkptno", miValueConst3 ); - bOk = bOk && miOutOfBandRecord.Add( miValueResult3 ); - const CMICmnMIValueConst miValueConst4( "{}" ); - const CMICmnMIValueResult miValueResult4( "frame", miValueConst4 ); - bOk = bOk && miOutOfBandRecord.Add( miValueResult4 ); - const CMIUtilString strThreadId( CMIUtilString::Format( "%d", vBrkPt.GetThreadIndex() ) ); - const CMICmnMIValueConst miValueConst5( strThreadId ); - const CMICmnMIValueResult miValueResult5( "thread-id", miValueConst5 ); - bOk = bOk && miOutOfBandRecord.Add( miValueResult5 ); - const CMICmnMIValueConst miValueConst6( "all" ); - const CMICmnMIValueResult miValueResult6( "stopped-threads", miValueConst6 ); - bOk = bOk && miOutOfBandRecord.Add( miValueResult6 ); - bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord ); - bOk = bOk && TextToStdout( "(gdb)" ); - return bOk; - } - - CMICmnLLDBDebugSessionInfo & rSession = CMICmnLLDBDebugSessionInfo::Instance(); - - lldb::SBFrame frame = thread.GetFrameAtIndex( 0 ); - lldb::addr_t pc = 0; - CMIUtilString fnName; - CMIUtilString fileName; - CMIUtilString path; - MIuint nLine = 0; - if( !rSession.GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET ), "MiStoppedAtBreakPoint()" ) ); - return MIstatus::failure; - } - - // MI print "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\"" - const CMICmnMIValueConst miValueConst( "breakpoint-hit" ); - const CMICmnMIValueResult miValueResult( "reason", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult ); - const CMICmnMIValueConst miValueConstA( "del" ); - const CMICmnMIValueResult miValueResultA( "disp", miValueConstA ); - bOk = miOutOfBandRecord.Add( miValueResultA ); - const CMIUtilString strBkp( CMIUtilString::Format( "%d", vBrkPtId ) ); - const CMICmnMIValueConst miValueConstB( strBkp ); - CMICmnMIValueResult miValueResultB( "bkptno", miValueConstB ); - bOk = bOk && miOutOfBandRecord.Add( miValueResultB ); - - // frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"} - if( bOk ) - { - CMICmnMIValueList miValueList( true ); - const MIuint maskVarTypes = 0x1000; - bOk = rSession.MIResponseFormVariableInfo2( frame, maskVarTypes, miValueList ); - - CMICmnMIValueTuple miValueTuple; - bOk = bOk && rSession.MIResponseFormFrameInfo2( pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple ); - const CMICmnMIValueResult miValueResult8( "frame", miValueTuple ); - bOk = bOk && miOutOfBandRecord.Add( miValueResult8 ); - } - - // Add to MI thread-id=\"%d\",stopped-threads=\"all\" - if( bOk ) - { - const CMIUtilString strThreadId( CMIUtilString::Format( "%d", thread.GetIndexID() ) ); - const CMICmnMIValueConst miValueConst8( strThreadId ); - const CMICmnMIValueResult miValueResult8( "thread-id", miValueConst8 ); - bOk = miOutOfBandRecord.Add( miValueResult8 ); - } - if( bOk ) - { - const CMICmnMIValueConst miValueConst9( "all" ); - const CMICmnMIValueResult miValueResult9( "stopped-threads", miValueConst9 ); - bOk = miOutOfBandRecord.Add( miValueResult9 ); - bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord ); - bOk = bOk && TextToStdout( "(gdb)" ); - } - - return MIstatus::success; + bool bOk = MIstatus::success; + + lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; + lldb::SBThread thread = rProcess.GetSelectedThread(); + const MIuint nFrame = thread.GetNumFrames(); + if (nFrame == 0) + { + // MI print "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={},thread-id=\"%d\",stopped-threads=\"all\"" + const CMICmnMIValueConst miValueConst("breakpoint-hit"); + const CMICmnMIValueResult miValueResult("reason", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + const CMICmnMIValueConst miValueConst2("del"); + const CMICmnMIValueResult miValueResult2("disp", miValueConst2); + bOk = miOutOfBandRecord.Add(miValueResult2); + const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId)); + const CMICmnMIValueConst miValueConst3(strBkp); + CMICmnMIValueResult miValueResult3("bkptno", miValueConst3); + bOk = bOk && miOutOfBandRecord.Add(miValueResult3); + const CMICmnMIValueConst miValueConst4("{}"); + const CMICmnMIValueResult miValueResult4("frame", miValueConst4); + bOk = bOk && miOutOfBandRecord.Add(miValueResult4); + const CMIUtilString strThreadId(CMIUtilString::Format("%d", vBrkPt.GetThreadIndex())); + const CMICmnMIValueConst miValueConst5(strThreadId); + const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5); + bOk = bOk && miOutOfBandRecord.Add(miValueResult5); + const CMICmnMIValueConst miValueConst6("all"); + const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6); + bOk = bOk && miOutOfBandRecord.Add(miValueResult6); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && TextToStdout("(gdb)"); + return bOk; + } + + CMICmnLLDBDebugSessionInfo &rSession = CMICmnLLDBDebugSessionInfo::Instance(); + + lldb::SBFrame frame = thread.GetFrameAtIndex(0); + lldb::addr_t pc = 0; + CMIUtilString fnName; + CMIUtilString fileName; + CMIUtilString path; + MIuint nLine = 0; + if (!rSession.GetFrameInfo(frame, pc, fnName, fileName, path, nLine)) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET), "MiStoppedAtBreakPoint()")); + return MIstatus::failure; + } + + // MI print + // "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\"" + const CMICmnMIValueConst miValueConst("breakpoint-hit"); + const CMICmnMIValueResult miValueResult("reason", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + const CMICmnMIValueConst miValueConstA("del"); + const CMICmnMIValueResult miValueResultA("disp", miValueConstA); + bOk = miOutOfBandRecord.Add(miValueResultA); + const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId)); + const CMICmnMIValueConst miValueConstB(strBkp); + CMICmnMIValueResult miValueResultB("bkptno", miValueConstB); + bOk = bOk && miOutOfBandRecord.Add(miValueResultB); + + // frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"} + if (bOk) + { + CMICmnMIValueList miValueList(true); + const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments; + bOk = rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, miValueList); + + CMICmnMIValueTuple miValueTuple; + bOk = bOk && rSession.MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple); + const CMICmnMIValueResult miValueResult8("frame", miValueTuple); + bOk = bOk && miOutOfBandRecord.Add(miValueResult8); + } + + // Add to MI thread-id=\"%d\",stopped-threads=\"all\" + if (bOk) + { + const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID())); + const CMICmnMIValueConst miValueConst8(strThreadId); + const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8); + bOk = miOutOfBandRecord.Add(miValueResult8); + } + if (bOk) + { + const CMICmnMIValueConst miValueConst9("all"); + const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9); + bOk = miOutOfBandRecord.Add(miValueResult9); + bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && TextToStdout("(gdb)"); + } + + return MIstatus::success; } - + //++ ------------------------------------------------------------------------------------ -// Details: Asynchronous event handler for LLDB Process stop reason trace. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Asynchronous event handler for LLDB Process stop reason trace. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace( void ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace(void) { - bool bOk = true; - lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - lldb::SBThread thread = rProcess.GetSelectedThread(); - const MIuint nFrame = thread.GetNumFrames(); - if( nFrame == 0 ) - { - // MI print "*stopped,reason=\"trace\",stopped-threads=\"all\"" - const CMICmnMIValueConst miValueConst( "trace" ); - const CMICmnMIValueResult miValueResult( "reason", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult ); - const CMICmnMIValueConst miValueConst2( "all" ); - const CMICmnMIValueResult miValueResult2( "stopped-threads", miValueConst2 ); - bOk = miOutOfBandRecord.Add( miValueResult2 ); - bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord ); - bOk = bOk && TextToStdout( "(gdb)" ); - return bOk; - } - - CMICmnLLDBDebugSessionInfo & rSession = CMICmnLLDBDebugSessionInfo::Instance(); - - // MI print "*stopped,reason=\"end-stepping-range\",frame={addr=\"0x%08x\",func=\"%s\",args=[\"%s\"],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\"" - lldb::SBFrame frame = thread.GetFrameAtIndex( 0 ); - lldb::addr_t pc = 0; - CMIUtilString fnName; - CMIUtilString fileName; - CMIUtilString path; - MIuint nLine = 0; - if( !rSession.GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET ), "HandleProcessEventStopReasonTrace()" ) ); - return MIstatus::failure; - } - - // Function args - CMICmnMIValueList miValueList( true ); - const MIuint maskVarTypes = 0x1000; - if( !rSession.MIResponseFormVariableInfo2( frame, maskVarTypes, miValueList ) ) - return MIstatus::failure; - CMICmnMIValueTuple miValueTuple; - if( !rSession.MIResponseFormFrameInfo2( pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple ) ) - return MIstatus::failure; - - const CMICmnMIValueConst miValueConst( "end-stepping-range" ); - const CMICmnMIValueResult miValueResult( "reason", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult ); - const CMICmnMIValueResult miValueResult2( "frame", miValueTuple ); - bOk = miOutOfBandRecord.Add( miValueResult2 ); - - // Add to MI thread-id=\"%d\",stopped-threads=\"all\" - if( bOk ) - { - const CMIUtilString strThreadId( CMIUtilString::Format( "%d", thread.GetIndexID() ) ); - const CMICmnMIValueConst miValueConst8( strThreadId ); - const CMICmnMIValueResult miValueResult8( "thread-id", miValueConst8 ); - bOk = miOutOfBandRecord.Add( miValueResult8 ); - } - if( bOk ) - { - const CMICmnMIValueConst miValueConst9( "all" ); - const CMICmnMIValueResult miValueResult9( "stopped-threads", miValueConst9 ); - bOk = miOutOfBandRecord.Add( miValueResult9 ); - bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord ); - bOk = bOk && TextToStdout( "(gdb)" ); - } - - return bOk; + bool bOk = true; + lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; + lldb::SBThread thread = rProcess.GetSelectedThread(); + const MIuint nFrame = thread.GetNumFrames(); + if (nFrame == 0) + { + // MI print "*stopped,reason=\"trace\",stopped-threads=\"all\"" + const CMICmnMIValueConst miValueConst("trace"); + const CMICmnMIValueResult miValueResult("reason", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + const CMICmnMIValueConst miValueConst2("all"); + const CMICmnMIValueResult miValueResult2("stopped-threads", miValueConst2); + bOk = miOutOfBandRecord.Add(miValueResult2); + bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && TextToStdout("(gdb)"); + return bOk; + } + + CMICmnLLDBDebugSessionInfo &rSession = CMICmnLLDBDebugSessionInfo::Instance(); + + // MI print + // "*stopped,reason=\"end-stepping-range\",frame={addr=\"0x%08x\",func=\"%s\",args=[\"%s\"],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\"" + lldb::SBFrame frame = thread.GetFrameAtIndex(0); + lldb::addr_t pc = 0; + CMIUtilString fnName; + CMIUtilString fileName; + CMIUtilString path; + MIuint nLine = 0; + if (!rSession.GetFrameInfo(frame, pc, fnName, fileName, path, nLine)) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET), "HandleProcessEventStopReasonTrace()")); + return MIstatus::failure; + } + + // Function args + CMICmnMIValueList miValueList(true); + const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments; + if (!rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, miValueList)) + return MIstatus::failure; + CMICmnMIValueTuple miValueTuple; + if (!rSession.MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple)) + return MIstatus::failure; + + const CMICmnMIValueConst miValueConst("end-stepping-range"); + const CMICmnMIValueResult miValueResult("reason", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + const CMICmnMIValueResult miValueResult2("frame", miValueTuple); + bOk = miOutOfBandRecord.Add(miValueResult2); + + // Add to MI thread-id=\"%d\",stopped-threads=\"all\" + if (bOk) + { + const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID())); + const CMICmnMIValueConst miValueConst8(strThreadId); + const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8); + bOk = miOutOfBandRecord.Add(miValueResult8); + } + if (bOk) + { + const CMICmnMIValueConst miValueConst9("all"); + const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9); + bOk = miOutOfBandRecord.Add(miValueResult9); + bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && TextToStdout("(gdb)"); + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Asynchronous function update selected thread. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Asynchronous function update selected thread. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread( void ) +bool +CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread(void) { - lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess(); - if( !process.IsValid() ) - return MIstatus::success; - - lldb::SBThread currentThread = process.GetSelectedThread(); - lldb::SBThread thread; - const lldb::StopReason eCurrentThreadStoppedReason = currentThread.GetStopReason(); - if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason == lldb::eStopReasonNone) ) - { - // Prefer a thread that has just completed its plan over another thread as current thread - lldb::SBThread planThread; - lldb::SBThread otherThread; - const size_t nThread = process.GetNumThreads(); - for( MIuint i = 0; i < nThread; i++ ) - { - // GetThreadAtIndex() uses a base 0 index - // GetThreadByIndexID() uses a base 1 index - thread = process.GetThreadAtIndex( i ); - const lldb::StopReason eThreadStopReason = thread.GetStopReason(); - switch( eThreadStopReason ) - { + lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess(); + if (!process.IsValid()) + return MIstatus::success; + + lldb::SBThread currentThread = process.GetSelectedThread(); + lldb::SBThread thread; + const lldb::StopReason eCurrentThreadStoppedReason = currentThread.GetStopReason(); + if (!currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || + (eCurrentThreadStoppedReason == lldb::eStopReasonNone)) + { + // Prefer a thread that has just completed its plan over another thread as current thread + lldb::SBThread planThread; + lldb::SBThread otherThread; + const size_t nThread = process.GetNumThreads(); + for (MIuint i = 0; i < nThread; i++) + { + // GetThreadAtIndex() uses a base 0 index + // GetThreadByIndexID() uses a base 1 index + thread = process.GetThreadAtIndex(i); + const lldb::StopReason eThreadStopReason = thread.GetStopReason(); + switch (eThreadStopReason) + { case lldb::eStopReasonTrace: case lldb::eStopReasonBreakpoint: case lldb::eStopReasonWatchpoint: case lldb::eStopReasonSignal: case lldb::eStopReasonException: - if( !otherThread.IsValid() ) + if (!otherThread.IsValid()) otherThread = thread; break; case lldb::eStopReasonPlanComplete: - if( !planThread.IsValid() ) + if (!planThread.IsValid()) planThread = thread; break; - case lldb::eStopReasonInvalid: + case lldb::eStopReasonInvalid: case lldb::eStopReasonNone: default: break; - } - } - if( planThread.IsValid() ) - process.SetSelectedThread( planThread ); - else if( otherThread.IsValid() ) - process.SetSelectedThread( otherThread ); - else - { - if( currentThread.IsValid() ) - thread = currentThread; - else - thread = process.GetThreadAtIndex( 0 ); - - if( thread.IsValid() ) - process.SetSelectedThread( thread ); - } - } // if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason == lldb::eStopReasonNone) ) - - return MIstatus::success; + } + } + if (planThread.IsValid()) + process.SetSelectedThread(planThread); + else if (otherThread.IsValid()) + process.SetSelectedThread(otherThread); + else + { + if (currentThread.IsValid()) + thread = currentThread; + else + thread = process.GetThreadAtIndex(0); + + if (thread.IsValid()) + process.SetSelectedThread(thread); + } + } // if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason == + // lldb::eStopReasonNone) ) + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Print to stdout "*running,thread-id=\"all\"", "(gdb)". -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Print to stdout "*running,thread-id=\"all\"", "(gdb)". +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning( void ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning(void) { - CMICmnMIValueConst miValueConst( "all" ); - CMICmnMIValueResult miValueResult( "thread-id", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Running, miValueResult ); - bool bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord ); - bOk = bOk && TextToStdout( "(gdb)" ); + CMICmnMIValueConst miValueConst("all"); + CMICmnMIValueResult miValueResult("thread-id", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Running, miValueResult); + bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && TextToStdout("(gdb)"); - return bOk; + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Print to stdout "=thread-exited,id=\"%ld\",group-id=\"i1\"", -// "=thread-group-exited,id=\"i1\",exit-code=\"0\""), -// "*stopped,reason=\"exited-normally\"", -// "(gdb)" -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Print to stdout "=thread-exited,id=\"%ld\",group-id=\"i1\"", +// "=thread-group-exited,id=\"i1\",exit-code=\"0\""), +// "*stopped,reason=\"exited-normally\"", +// "(gdb)" +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited( void ) +bool +CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited(void) { - const CMIUtilString strId( CMIUtilString::Format( "%ld", 1 ) ); - CMICmnMIValueConst miValueConst( strId ); - CMICmnMIValueResult miValueResult( "id", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult ); - CMICmnMIValueConst miValueConst2( "i1" ); - CMICmnMIValueResult miValueResult2( "group-id", miValueConst2 ); - bool bOk = miOutOfBandRecord.Add( miValueResult2 ); - bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord ); - if( bOk ) - { - CMICmnMIValueConst miValueConst3( "i1" ); - CMICmnMIValueResult miValueResult3( "id", miValueConst3 ); - CMICmnMIOutOfBandRecord miOutOfBandRecord2( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult3 ); - CMICmnMIValueConst miValueConst2( "0" ); - CMICmnMIValueResult miValueResult2( "exit-code", miValueConst2 ); - bOk = miOutOfBandRecord2.Add( miValueResult2 ); - bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord2 ); - } - if( bOk ) - { - CMICmnMIValueConst miValueConst4( "exited-normally" ); - CMICmnMIValueResult miValueResult4( "reason", miValueConst4 ); - CMICmnMIOutOfBandRecord miOutOfBandRecord3( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult4 ); - bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord3 ); - } - bOk = bOk && TextToStdout( "(gdb)" ); - - return bOk; + const CMIUtilString strId(CMIUtilString::Format("%ld", 1)); + CMICmnMIValueConst miValueConst(strId); + CMICmnMIValueResult miValueResult("id", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult); + CMICmnMIValueConst miValueConst2("i1"); + CMICmnMIValueResult miValueResult2("group-id", miValueConst2); + bool bOk = miOutOfBandRecord.Add(miValueResult2); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); + if (bOk) + { + CMICmnMIValueConst miValueConst3("i1"); + CMICmnMIValueResult miValueResult3("id", miValueConst3); + CMICmnMIOutOfBandRecord miOutOfBandRecord2(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult3); + CMICmnMIValueConst miValueConst2("0"); + CMICmnMIValueResult miValueResult2("exit-code", miValueConst2); + bOk = miOutOfBandRecord2.Add(miValueResult2); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord2); + } + if (bOk) + { + CMICmnMIValueConst miValueConst4("exited-normally"); + CMICmnMIValueResult miValueResult4("reason", miValueConst4); + CMICmnMIOutOfBandRecord miOutOfBandRecord3(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult4); + bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord3); + } + bOk = bOk && TextToStdout("(gdb)"); + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Drain all stdout so we don't see any output come after we print our prompts. -// The process has stuff waiting for stdout; get it and write it out to the -// appropriate place. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Drain all stdout so we don't see any output come after we print our prompts. +// The process has stuff waiting for stdout; get it and write it out to the +// appropriate place. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::GetProcessStdout( void ) +bool +CMICmnLLDBDebuggerHandleEvents::GetProcessStdout(void) { - bool bOk = MIstatus::success; - - char c; - size_t nBytes = 0; - CMIUtilString text; - lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess(); - while( process.GetSTDOUT( &c, 1 ) > 0 ) - { - CMIUtilString str; - if( ConvertPrintfCtrlCodeToString( c, str ) ) - text += str; - nBytes++; - } - if( nBytes > 0 ) - { - const CMIUtilString t( CMIUtilString::Format( "~\"%s\"", text.c_str() ) ); - bOk = TextToStdout( t ); - } - - return bOk; + bool bOk = MIstatus::success; + + char c; + size_t nBytes = 0; + CMIUtilString text; + lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess(); + while (process.GetSTDOUT(&c, 1) > 0) + { + CMIUtilString str; + if (ConvertPrintfCtrlCodeToString(c, str)) + text += str; + nBytes++; + } + if (nBytes > 0) + { + const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.c_str())); + bOk = TextToStdout(t); + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Drain all stderr so we don't see any output come after we print our prompts. -// The process has stuff waiting for stderr; get it and write it out to the -// appropriate place. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Drain all stderr so we don't see any output come after we print our prompts. +// The process has stuff waiting for stderr; get it and write it out to the +// appropriate place. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::GetProcessStderr( void ) +bool +CMICmnLLDBDebuggerHandleEvents::GetProcessStderr(void) { - bool bOk = MIstatus::success; - - char c; - size_t nBytes = 0; - CMIUtilString text; - lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess(); - while( process.GetSTDERR( &c, 1 ) > 0 ) - { - CMIUtilString str; - if( ConvertPrintfCtrlCodeToString( c, str ) ) - text += str; - nBytes++; - } - if( nBytes > 0 ) - { - const CMIUtilString t( CMIUtilString::Format( "~\"%s\"", text.c_str() ) ); - bOk = TextToStdout( t ); - } - - return bOk; + bool bOk = MIstatus::success; + + char c; + size_t nBytes = 0; + CMIUtilString text; + lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess(); + while (process.GetSTDERR(&c, 1) > 0) + { + CMIUtilString str; + if (ConvertPrintfCtrlCodeToString(c, str)) + text += str; + nBytes++; + } + if (nBytes > 0) + { + const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.c_str())); + bOk = TextToStdout(t); + } + + return bOk; } - + //++ ------------------------------------------------------------------------------------ -// Details: Convert text stream control codes to text equivalent. -// Type: Method. -// Args: vCtrl - (R) The control code. -// vwrStrEquivalent - (W) The text equivalent. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Convert text stream control codes to text equivalent. +// Type: Method. +// Args: vCtrl - (R) The control code. +// vwrStrEquivalent - (W) The text equivalent. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::ConvertPrintfCtrlCodeToString( const MIchar vCtrl, CMIUtilString & vwrStrEquivalent ) +bool +CMICmnLLDBDebuggerHandleEvents::ConvertPrintfCtrlCodeToString(const MIchar vCtrl, CMIUtilString &vwrStrEquivalent) { - switch( vCtrl ) - { - case '\033': vwrStrEquivalent = "\\e"; break; - case '\a': vwrStrEquivalent = "\\a"; break; - case '\b': vwrStrEquivalent = "\\b"; break; - case '\f': vwrStrEquivalent = "\\f"; break; - case '\n': vwrStrEquivalent = "\\n"; break; - case '\r': vwrStrEquivalent = "\\r"; break; - case '\t': vwrStrEquivalent = "\\t"; break; - case '\v': vwrStrEquivalent = "\\v"; break; - default: - vwrStrEquivalent = CMIUtilString::Format( "%c", vCtrl ); - break; - } - - return MIstatus::success; + switch (vCtrl) + { + case '\033': + vwrStrEquivalent = "\\e"; + break; + case '\a': + vwrStrEquivalent = "\\a"; + break; + case '\b': + vwrStrEquivalent = "\\b"; + break; + case '\f': + vwrStrEquivalent = "\\f"; + break; + case '\n': + vwrStrEquivalent = "\\n"; + break; + case '\r': + vwrStrEquivalent = "\\r"; + break; + case '\t': + vwrStrEquivalent = "\\t"; + break; + case '\v': + vwrStrEquivalent = "\\v"; + break; + default: + vwrStrEquivalent = CMIUtilString::Format("%c", vCtrl); + break; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Asynchronous event function check for state changes. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Asynchronous event function check for state changes. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges( void ) +bool +CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges(void) { - lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - if( !rProcess.IsValid() ) - return MIstatus::success; - lldb::SBTarget & rTarget = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget; - if( !rTarget.IsValid() ) - return MIstatus::success; + lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; + if (!rProcess.IsValid()) + return MIstatus::success; + lldb::SBTarget &rTarget = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget; + if (!rTarget.IsValid()) + return MIstatus::success; - bool bOk = MIstatus::success; + bool bOk = MIstatus::success; - // Check for created threads + // Check for created threads const MIuint nThread = rProcess.GetNumThreads(); - for( MIuint i = 0; i < nThread; i++ ) - { - // GetThreadAtIndex() uses a base 0 index - // GetThreadByIndexID() uses a base 1 index - lldb::SBThread thread = rProcess.GetThreadAtIndex( i ); - if( !thread.IsValid() ) - continue; - - CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it = CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin(); - bool bFound = false; - while( it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end() ) - { - const MIuint nThreadId = *it; - if( nThreadId == i ) - { - bFound = true; - break; - } - - // Next - ++it; - } - if( !bFound ) - { - CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.push_back( i ); - - // Form MI "=thread-created,id=\"%d\",group-id=\"i1\"" - const CMIUtilString strValue( CMIUtilString::Format( "%d", thread.GetIndexID() ) ); - const CMICmnMIValueConst miValueConst( strValue ); - const CMICmnMIValueResult miValueResult( "id", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, miValueResult ); - const CMICmnMIValueConst miValueConst2( "i1" ); - const CMICmnMIValueResult miValueResult2( "group-id", miValueConst2 ); - bOk = miOutOfBand.Add( miValueResult2 ); - bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBand ); - if( !bOk ) - return MIstatus::failure; - } - } - - lldb::SBThread currentThread = rProcess.GetSelectedThread(); - if( currentThread.IsValid() ) - { - const MIuint threadId = currentThread.GetIndexID(); - if( CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread != threadId ) - { - CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread = threadId; - - // Form MI "=thread-selected,id=\"%d\"" - const CMIUtilString strValue( CMIUtilString::Format( "%d", currentThread.GetIndexID() ) ); - const CMICmnMIValueConst miValueConst( strValue ); - const CMICmnMIValueResult miValueResult( "id", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, miValueResult ); - if( !MiOutOfBandRecordToStdout( miOutOfBand ) ) - return MIstatus::failure; - } - } - - // Check for invalid (removed) threads - CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it = CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin(); - while( it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end() ) - { - const MIuint nThreadId = *it; - lldb::SBThread thread = rProcess.GetThreadAtIndex( nThreadId ); - if( !thread.IsValid() ) - { - // Form MI "=thread-exited,id=\"%ld\",group-id=\"i1\"" - const CMIUtilString strValue( CMIUtilString::Format( "%ld", thread.GetIndexID() ) ); - const CMICmnMIValueConst miValueConst( strValue ); - const CMICmnMIValueResult miValueResult( "id", miValueConst ); - CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult ); - const CMICmnMIValueConst miValueConst2( "i1" ); - const CMICmnMIValueResult miValueResult2( "group-id", miValueConst2 ); - bOk = miOutOfBand.Add( miValueResult2 ); - bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBand ); - if( !bOk ) - return MIstatus::failure; - } - - // Next - ++it; - } - - return TextToStdout( "(gdb)" ); + for (MIuint i = 0; i < nThread; i++) + { + // GetThreadAtIndex() uses a base 0 index + // GetThreadByIndexID() uses a base 1 index + lldb::SBThread thread = rProcess.GetThreadAtIndex(i); + if (!thread.IsValid()) + continue; + + CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it = + CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin(); + bool bFound = false; + while (it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end()) + { + const MIuint nThreadId = *it; + if (nThreadId == i) + { + bFound = true; + break; + } + + // Next + ++it; + } + if (!bFound) + { + CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.push_back(i); + + // Form MI "=thread-created,id=\"%d\",group-id=\"i1\"" + const CMIUtilString strValue(CMIUtilString::Format("%d", thread.GetIndexID())); + const CMICmnMIValueConst miValueConst(strValue); + const CMICmnMIValueResult miValueResult("id", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, miValueResult); + const CMICmnMIValueConst miValueConst2("i1"); + const CMICmnMIValueResult miValueResult2("group-id", miValueConst2); + bOk = miOutOfBand.Add(miValueResult2); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBand); + if (!bOk) + return MIstatus::failure; + } + } + + lldb::SBThread currentThread = rProcess.GetSelectedThread(); + if (currentThread.IsValid()) + { + const MIuint threadId = currentThread.GetIndexID(); + if (CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread != threadId) + { + CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread = threadId; + + // Form MI "=thread-selected,id=\"%d\"" + const CMIUtilString strValue(CMIUtilString::Format("%d", currentThread.GetIndexID())); + const CMICmnMIValueConst miValueConst(strValue); + const CMICmnMIValueResult miValueResult("id", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, miValueResult); + if (!MiOutOfBandRecordToStdout(miOutOfBand)) + return MIstatus::failure; + } + } + + // Check for invalid (removed) threads + CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it = CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin(); + while (it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end()) + { + const MIuint nThreadId = *it; + lldb::SBThread thread = rProcess.GetThreadAtIndex(nThreadId); + if (!thread.IsValid()) + { + // Form MI "=thread-exited,id=\"%ld\",group-id=\"i1\"" + const CMIUtilString strValue(CMIUtilString::Format("%ld", thread.GetIndexID())); + const CMICmnMIValueConst miValueConst(strValue); + const CMICmnMIValueResult miValueResult("id", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult); + const CMICmnMIValueConst miValueConst2("i1"); + const CMICmnMIValueResult miValueResult2("group-id", miValueConst2); + bOk = miOutOfBand.Add(miValueResult2); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBand); + if (!bOk) + return MIstatus::failure; + } + + // Next + ++it; + } + + return TextToStdout("(gdb)"); } //++ ------------------------------------------------------------------------------------ -// Details: Take a fully formed MI result record and send to the stdout stream. -// Also output to the MI Log file. -// Type: Method. -// Args: vrMiResultRecord - (R) MI result record object. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Take a fully formed MI result record and send to the stdout stream. +// Also output to the MI Log file. +// Type: Method. +// Args: vrMiResultRecord - (R) MI result record object. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::MiResultRecordToStdout( const CMICmnMIResultRecord & vrMiResultRecord ) +bool +CMICmnLLDBDebuggerHandleEvents::MiResultRecordToStdout(const CMICmnMIResultRecord &vrMiResultRecord) { - return TextToStdout( vrMiResultRecord.GetString() ); + return TextToStdout(vrMiResultRecord.GetString()); } //++ ------------------------------------------------------------------------------------ -// Details: Take a fully formed MI Out-of-band record and send to the stdout stream. -// Also output to the MI Log file. -// Type: Method. -// Args: vrMiOutOfBandRecord - (R) MI Out-of-band record object. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Take a fully formed MI Out-of-band record and send to the stdout stream. +// Also output to the MI Log file. +// Type: Method. +// Args: vrMiOutOfBandRecord - (R) MI Out-of-band record object. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::MiOutOfBandRecordToStdout( const CMICmnMIOutOfBandRecord & vrMiOutOfBandRecord ) +bool +CMICmnLLDBDebuggerHandleEvents::MiOutOfBandRecordToStdout(const CMICmnMIOutOfBandRecord &vrMiOutOfBandRecord) { - return TextToStdout( vrMiOutOfBandRecord.GetString() ); + return TextToStdout(vrMiOutOfBandRecord.GetString()); } //++ ------------------------------------------------------------------------------------ -// Details: Take a text data and send to the stdout stream. Also output to the MI Log -// file. -// Type: Method. -// Args: vrTxt - (R) Text. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Take a text data and send to the stdout stream. Also output to the MI Log +// file. +// Type: Method. +// Args: vrTxt - (R) Text. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::TextToStdout( const CMIUtilString & vrTxt ) +bool +CMICmnLLDBDebuggerHandleEvents::TextToStdout(const CMIUtilString &vrTxt) { - return CMICmnStreamStdout::TextToStdout( vrTxt ); + return CMICmnStreamStdout::TextToStdout(vrTxt); } //++ ------------------------------------------------------------------------------------ -// Details: Take a text data and send to the stderr stream. Also output to the MI Log -// file. -// Type: Method. -// Args: vrTxt - (R) Text. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Take a text data and send to the stderr stream. Also output to the MI Log +// file. +// Type: Method. +// Args: vrTxt - (R) Text. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBDebuggerHandleEvents::TextToStderr( const CMIUtilString & vrTxt ) +bool +CMICmnLLDBDebuggerHandleEvents::TextToStderr(const CMIUtilString &vrTxt) { - return CMICmnStreamStderr::TextToStderr( vrTxt ); + return CMICmnStreamStderr::TextToStderr(vrTxt); } diff --git a/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h b/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h index fdcb2ea4e147..65b397c13fd9 100644 --- a/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h +++ b/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLLDBDebuggerHandleEvents.h +// File: MICmnLLDBDebuggerHandleEvents.h // -// Overview: CMICmnLLDBDebuggerHandleEvents interface. +// Overview: CMICmnLLDBDebuggerHandleEvents interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -33,65 +33,62 @@ class CMICmnStreamStdout; class CMICmnMIOutOfBandRecord; //++ ============================================================================ -// Details: MI class to take LLDB SBEvent objects, filter them and form -// MI Out-of-band records from the information inside the event object. -// These records are then pushed to stdout. -// A singleton class. -// Gotchas: None. -// Authors: Illya Rudkin 02/03/2014. -// Changes: None. +// Details: MI class to take LLDB SBEvent objects, filter them and form +// MI Out-of-band records from the information inside the event object. +// These records are then pushed to stdout. +// A singleton class. +// Gotchas: None. +// Authors: Illya Rudkin 02/03/2014. +// Changes: None. //-- -class CMICmnLLDBDebuggerHandleEvents -: public CMICmnBase -, public MI::ISingleton< CMICmnLLDBDebuggerHandleEvents > +class CMICmnLLDBDebuggerHandleEvents : public CMICmnBase, public MI::ISingleton { - friend class MI::ISingleton< CMICmnLLDBDebuggerHandleEvents >; + friend class MI::ISingleton; -// Methods: -public: - bool Initialize( void ); - bool Shutdown( void ); - // - bool HandleEvent( const lldb::SBEvent & vEvent, bool & vrbHandledEvent, bool & vrbExitAppEvent ); + // Methods: + public: + bool Initialize(void); + bool Shutdown(void); + // + bool HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent, bool &vrbExitAppEvent); -// Methods: -private: - /* ctor */ CMICmnLLDBDebuggerHandleEvents( void ); - /* ctor */ CMICmnLLDBDebuggerHandleEvents( const CMICmnLLDBDebuggerHandleEvents & ); - void operator=( const CMICmnLLDBDebuggerHandleEvents & ); - // - bool ChkForStateChanges( void ); - bool GetProcessStdout( void ); - bool GetProcessStderr( void ); - bool HandleEventSBBreakPoint( const lldb::SBEvent & vEvent ); - bool HandleEventSBBreakpointCmn( const lldb::SBEvent & vEvent ); - bool HandleEventSBBreakpointAdded( const lldb::SBEvent & vEvent ); - bool HandleEventSBBreakpointLocationsAdded( const lldb::SBEvent & vEvent ); - bool HandleEventSBProcess( const lldb::SBEvent & vEvent, bool & vrbExitAppEvent ); - bool HandleEventSBThread( const lldb::SBEvent & vEvent ); - bool HandleEventSBThreadBitStackChanged( const lldb::SBEvent & vEvent ); - bool HandleEventSBThreadSuspended( const lldb::SBEvent & vEvent ); - bool HandleEventSBCommandInterpreter( const lldb::SBEvent & vEvent ); - bool HandleProcessEventBroadcastBitStateChanged( const lldb::SBEvent & vEvent, bool & vrbExitAppEvent ); - bool HandleProcessEventStateRunning( void ); - bool HandleProcessEventStateExited( void ); - bool HandleProcessEventStateStopped( bool & vwrbShouldBrk ); - bool HandleProcessEventStopReasonTrace( void ); - bool HandleProcessEventStopReasonBreakpoint( void ); - bool HandleProcessEventStopSignal( bool & vwrbShouldBrk ); - bool HandleProcessEventStateSuspended( const lldb::SBEvent & vEvent ); - bool MiHelpGetCurrentThreadFrame( CMICmnMIValueTuple & vwrMiValueTuple ); - bool MiResultRecordToStdout( const CMICmnMIResultRecord & vrMiResultRecord ); - bool MiOutOfBandRecordToStdout( const CMICmnMIOutOfBandRecord & vrMiResultRecord ); - bool MiStoppedAtBreakPoint( const MIuint64 vBrkPtId, const lldb::SBBreakpoint & vBrkPt ); - bool TextToStdout( const CMIUtilString & vrTxt ); - bool TextToStderr( const CMIUtilString & vrTxt ); - bool UpdateSelectedThread( void ); - bool ConvertPrintfCtrlCodeToString( const MIchar vCtrl, CMIUtilString & vwrStrEquivalent ); + // Methods: + private: + /* ctor */ CMICmnLLDBDebuggerHandleEvents(void); + /* ctor */ CMICmnLLDBDebuggerHandleEvents(const CMICmnLLDBDebuggerHandleEvents &); + void operator=(const CMICmnLLDBDebuggerHandleEvents &); + // + bool ChkForStateChanges(void); + bool GetProcessStdout(void); + bool GetProcessStderr(void); + bool HandleEventSBBreakPoint(const lldb::SBEvent &vEvent); + bool HandleEventSBBreakpointCmn(const lldb::SBEvent &vEvent); + bool HandleEventSBBreakpointAdded(const lldb::SBEvent &vEvent); + bool HandleEventSBBreakpointLocationsAdded(const lldb::SBEvent &vEvent); + bool HandleEventSBProcess(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent); + bool HandleEventSBThread(const lldb::SBEvent &vEvent); + bool HandleEventSBThreadBitStackChanged(const lldb::SBEvent &vEvent); + bool HandleEventSBThreadSuspended(const lldb::SBEvent &vEvent); + bool HandleEventSBCommandInterpreter(const lldb::SBEvent &vEvent); + bool HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent); + bool HandleProcessEventStateRunning(void); + bool HandleProcessEventStateExited(void); + bool HandleProcessEventStateStopped(bool &vwrbShouldBrk); + bool HandleProcessEventStopReasonTrace(void); + bool HandleProcessEventStopReasonBreakpoint(void); + bool HandleProcessEventStopSignal(bool &vwrbShouldBrk); + bool HandleProcessEventStateSuspended(const lldb::SBEvent &vEvent); + bool MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple &vwrMiValueTuple); + bool MiResultRecordToStdout(const CMICmnMIResultRecord &vrMiResultRecord); + bool MiOutOfBandRecordToStdout(const CMICmnMIOutOfBandRecord &vrMiResultRecord); + bool MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, const lldb::SBBreakpoint &vBrkPt); + bool TextToStdout(const CMIUtilString &vrTxt); + bool TextToStderr(const CMIUtilString &vrTxt); + bool UpdateSelectedThread(void); + bool ConvertPrintfCtrlCodeToString(const MIchar vCtrl, CMIUtilString &vwrStrEquivalent); -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMICmnLLDBDebuggerHandleEvents( void ); + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMICmnLLDBDebuggerHandleEvents(void); }; - diff --git a/tools/lldb-mi/MICmnLLDBProxySBValue.cpp b/tools/lldb-mi/MICmnLLDBProxySBValue.cpp index 78ef76bf698f..a4f36b400fa7 100644 --- a/tools/lldb-mi/MICmnLLDBProxySBValue.cpp +++ b/tools/lldb-mi/MICmnLLDBProxySBValue.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLLDBProxySBValue.cpp +// File: MICmnLLDBProxySBValue.cpp // -// Overview: CMICmnLLDBProxySBValue implementation. +// Overview: CMICmnLLDBProxySBValue implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #include @@ -30,124 +30,125 @@ #include "MICmnLLDBDebugSessionInfo.h" //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the numerical value from the SBValue object. If the function fails -// it could indicate the SBValue object does not represent an internal type. -// Type: Static method. -// Args: vrValue - (R) The SBValue object to get a value from. -// vwValue - (W) The numerical value. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Retrieve the numerical value from the SBValue object. If the function fails +// it could indicate the SBValue object does not represent an internal type. +// Type: Static method. +// Args: vrValue - (R) The SBValue object to get a value from. +// vwValue - (W) The numerical value. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBProxySBValue::GetValueAsUnsigned( const lldb::SBValue & vrValue, MIuint64 & vwValue ) +bool +CMICmnLLDBProxySBValue::GetValueAsUnsigned(const lldb::SBValue &vrValue, MIuint64 &vwValue) { - lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValue ); - bool bCompositeType = true; - MIuint64 nFailValue = 0; - MIuint64 nValue = rValue.GetValueAsUnsigned( nFailValue ); - if( nValue == nFailValue ) - { - nFailValue = 5; // Some arbitary number - nValue = rValue.GetValueAsUnsigned( nFailValue ); - if( nValue != nFailValue ) - { - bCompositeType = false; - vwValue = nValue; - } - } - else - { - bCompositeType = false; - vwValue = nValue; - } + lldb::SBValue &rValue = const_cast(vrValue); + bool bCompositeType = true; + MIuint64 nFailValue = 0; + MIuint64 nValue = rValue.GetValueAsUnsigned(nFailValue); + if (nValue == nFailValue) + { + nFailValue = 5; // Some arbitary number + nValue = rValue.GetValueAsUnsigned(nFailValue); + if (nValue != nFailValue) + { + bCompositeType = false; + vwValue = nValue; + } + } + else + { + bCompositeType = false; + vwValue = nValue; + } - return (bCompositeType ? MIstatus::failure : MIstatus::success); + return (bCompositeType ? MIstatus::failure : MIstatus::success); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the numerical value from the SBValue object. If the function fails -// it could indicate the SBValue object does not represent an internal type. -// Type: Static method. -// Args: vrValue - (R) The SBValue object to get a value from. -// vwValue - (W) The numerical value. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Retrieve the numerical value from the SBValue object. If the function fails +// it could indicate the SBValue object does not represent an internal type. +// Type: Static method. +// Args: vrValue - (R) The SBValue object to get a value from. +// vwValue - (W) The numerical value. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnLLDBProxySBValue::GetValueAsSigned( const lldb::SBValue & vrValue, MIint64 & vwValue ) +bool +CMICmnLLDBProxySBValue::GetValueAsSigned(const lldb::SBValue &vrValue, MIint64 &vwValue) { - lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValue ); - bool bCompositeType = true; - MIuint64 nFailValue = 0; - MIuint64 nValue = rValue.GetValueAsSigned( nFailValue ); - if( nValue == nFailValue ) - { - nFailValue = 5; // Some arbitary number - nValue = rValue.GetValueAsSigned( nFailValue ); - if( nValue != nFailValue ) - { - bCompositeType = false; - vwValue = nValue; - } - } - else - { - bCompositeType = false; - vwValue = nValue; - } + lldb::SBValue &rValue = const_cast(vrValue); + bool bCompositeType = true; + MIuint64 nFailValue = 0; + MIuint64 nValue = rValue.GetValueAsSigned(nFailValue); + if (nValue == nFailValue) + { + nFailValue = 5; // Some arbitary number + nValue = rValue.GetValueAsSigned(nFailValue); + if (nValue != nFailValue) + { + bCompositeType = false; + vwValue = nValue; + } + } + else + { + bCompositeType = false; + vwValue = nValue; + } - return (bCompositeType ? MIstatus::failure : MIstatus::success); + return (bCompositeType ? MIstatus::failure : MIstatus::success); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the NUL terminated string from the SBValue object if it of the type -// unsigned char *. -// Type: Static method. -// Args: vrValue - (R) The SBValue object to get a value from. -// vwCString - (W) The text data '\0' terminated. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed, not suitable type. -// Throws: None. +// Details: Retrieve the NUL terminated string from the SBValue object if it of the type +// unsigned char *. +// Type: Static method. +// Args: vrValue - (R) The SBValue object to get a value from. +// vwCString - (W) The text data '\0' terminated. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed, not suitable type. +// Throws: None. //-- -bool CMICmnLLDBProxySBValue::GetCString( const lldb::SBValue & vrValue, CMIUtilString & vwCString ) +bool +CMICmnLLDBProxySBValue::GetCString(const lldb::SBValue &vrValue, CMIUtilString &vwCString) { - lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValue ); - const MIchar * pCType = rValue.GetTypeName(); - if( pCType == nullptr ) - return MIstatus::failure; - - const MIchar * pType = "unsigned char *"; - if( !CMIUtilString::Compare( pCType, pType ) ) - return MIstatus::failure; + lldb::SBValue &rValue = const_cast(vrValue); + const MIchar *pCType = rValue.GetTypeName(); + if (pCType == nullptr) + return MIstatus::failure; - const CMIUtilString strAddr( rValue.GetValue() ); - MIint64 nNum = 0; - if( !strAddr.ExtractNumber( nNum ) ) - return MIstatus::failure; + const MIchar *pType = "unsigned char *"; + if (!CMIUtilString::Compare(pCType, pType)) + return MIstatus::failure; - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; - MIuint nBufferSize = 64; - bool bNeedResize = false; - MIchar * pBuffer = static_cast< MIchar * >( ::malloc( nBufferSize ) ); - do - { - lldb::SBError error; - const size_t nReadSize = rProcess.ReadCStringFromMemory( (lldb::addr_t) nNum, pBuffer, nBufferSize, error ); - if( nReadSize == (nBufferSize - 1) ) - { - bNeedResize = true; - nBufferSize = nBufferSize << 1; - pBuffer = static_cast< MIchar * >( ::realloc( pBuffer, nBufferSize ) ); - } - else - bNeedResize = false; - } - while( bNeedResize ); + const CMIUtilString strAddr(rValue.GetValue()); + MIint64 nNum = 0; + if (!strAddr.ExtractNumber(nNum)) + return MIstatus::failure; - vwCString = pBuffer; - free( (void *) pBuffer ); + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + MIuint nBufferSize = 64; + bool bNeedResize = false; + MIchar *pBuffer = static_cast(::malloc(nBufferSize)); + do + { + lldb::SBError error; + const size_t nReadSize = rProcess.ReadCStringFromMemory((lldb::addr_t)nNum, pBuffer, nBufferSize, error); + if (nReadSize == (nBufferSize - 1)) + { + bNeedResize = true; + nBufferSize = nBufferSize << 1; + pBuffer = static_cast(::realloc(pBuffer, nBufferSize)); + } + else + bNeedResize = false; + } while (bNeedResize); - return MIstatus::success; -} + vwCString = pBuffer; + free((void *)pBuffer); + return MIstatus::success; +} diff --git a/tools/lldb-mi/MICmnLLDBProxySBValue.h b/tools/lldb-mi/MICmnLLDBProxySBValue.h index 7e743cdb7eaf..e21eb95a2dd9 100644 --- a/tools/lldb-mi/MICmnLLDBProxySBValue.h +++ b/tools/lldb-mi/MICmnLLDBProxySBValue.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLLDBProxySBValue.h +// File: MICmnLLDBProxySBValue.h // -// Overview: CMICmnLLDBProxySBValue interface. +// Overview: CMICmnLLDBProxySBValue interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -31,17 +31,17 @@ class CMIUtilString; //++ ============================================================================ -// Details: MI proxy wrapper class to lldb::SBValue. The class provides functionality -// to assist in the use of SBValue's parculiar function usage. -// Gotchas: None. -// Authors: Illya Rudkin 03/04/2014. -// Changes: None. +// Details: MI proxy wrapper class to lldb::SBValue. The class provides functionality +// to assist in the use of SBValue's parculiar function usage. +// Gotchas: None. +// Authors: Illya Rudkin 03/04/2014. +// Changes: None. //-- class CMICmnLLDBProxySBValue { -// Statics: -public: - static bool GetValueAsSigned( const lldb::SBValue & vrValue, MIint64 & vwValue ); - static bool GetValueAsUnsigned( const lldb::SBValue & vrValue, MIuint64 & vwValue ); - static bool GetCString( const lldb::SBValue & vrValue, CMIUtilString & vwCString ); + // Statics: + public: + static bool GetValueAsSigned(const lldb::SBValue &vrValue, MIint64 &vwValue); + static bool GetValueAsUnsigned(const lldb::SBValue &vrValue, MIuint64 &vwValue); + static bool GetCString(const lldb::SBValue &vrValue, CMIUtilString &vwCString); }; diff --git a/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp b/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp index 004be071260a..847bba2c8d0a 100644 --- a/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp +++ b/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLLDBUtilSBValue.cpp +// File: MICmnLLDBUtilSBValue.cpp // -// Overview: CMICmnLLDBUtilSBValue implementation. +// Overview: CMICmnLLDBUtilSBValue implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -25,300 +25,312 @@ #include "MICmnLLDBDebugSessionInfo.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBUtilSBValue constructor. -// Type: Method. -// Args: vrValue - (R) The LLDb value object. -// vbHandleCharType - (R) True = Yes return text molding to char type, -// False = just return data. -// Return: None. -// Throws: None. +// Details: CMICmnLLDBUtilSBValue constructor. +// Type: Method. +// Args: vrValue - (R) The LLDb value object. +// vbHandleCharType - (R) True = Yes return text molding to char type, +// False = just return data. +// Return: None. +// Throws: None. //-- -CMICmnLLDBUtilSBValue::CMICmnLLDBUtilSBValue( const lldb::SBValue & vrValue, const bool vbHandleCharType /* = false */ ) -: m_rValue( const_cast< lldb::SBValue & >( vrValue ) ) -, m_pUnkwn( "??" ) -, m_bHandleCharType( vbHandleCharType ) +CMICmnLLDBUtilSBValue::CMICmnLLDBUtilSBValue(const lldb::SBValue &vrValue, const bool vbHandleCharType /* = false */) + : m_rValue(const_cast(vrValue)) + , m_pUnkwn("??") + , m_bHandleCharType(vbHandleCharType) { - m_bValidSBValue = m_rValue.IsValid(); + m_bValidSBValue = m_rValue.IsValid(); } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLLDBUtilSBValue destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnLLDBUtilSBValue destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnLLDBUtilSBValue::~CMICmnLLDBUtilSBValue( void ) +CMICmnLLDBUtilSBValue::~CMICmnLLDBUtilSBValue(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve from the LLDB SB Value object the name of the variable. If the name -// is invalid (or the SBValue object invalid) then "??" is returned. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Name of the variable or "??" for unknown. -// Throws: None. +// Details: Retrieve from the LLDB SB Value object the name of the variable. If the name +// is invalid (or the SBValue object invalid) then "??" is returned. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Name of the variable or "??" for unknown. +// Throws: None. //-- -CMIUtilString CMICmnLLDBUtilSBValue::GetName( void ) const +CMIUtilString +CMICmnLLDBUtilSBValue::GetName(void) const { - const MIchar * pName = m_bValidSBValue ? m_rValue.GetName() : nullptr; - const CMIUtilString text( (pName != nullptr) ? pName : m_pUnkwn ); - - return text; + const MIchar *pName = m_bValidSBValue ? m_rValue.GetName() : nullptr; + const CMIUtilString text((pName != nullptr) ? pName : m_pUnkwn); + + return text; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve from the LLDB SB Value object the value of the variable described in -// text. If the value is invalid (or the SBValue object invalid) then "??" is -// returned. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Text description of the variable's value or "??". -// Throws: None. +// Details: Retrieve from the LLDB SB Value object the value of the variable described in +// text. If the value is invalid (or the SBValue object invalid) then "??" is +// returned. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Text description of the variable's value or "??". +// Throws: None. //-- -CMIUtilString CMICmnLLDBUtilSBValue::GetValue( void ) const +CMIUtilString +CMICmnLLDBUtilSBValue::GetValue(void) const { - CMIUtilString text; - - if( m_bHandleCharType && IsCharType() ) - { - const lldb::addr_t addr = m_rValue.GetLoadAddress(); - text = CMIUtilString::Format( "0x%08x", addr ); - const CMIUtilString cString( GetValueCString() ); - if( !cString.empty() ) - text += CMIUtilString::Format( " %s", cString.c_str() ); - } - else - { - const MIchar * pValue = m_bValidSBValue ? m_rValue.GetValue() : nullptr; - text = (pValue != nullptr) ? pValue : m_pUnkwn; - } - - return text; + CMIUtilString text; + + if (m_bHandleCharType && IsCharType()) + { + const lldb::addr_t addr = m_rValue.GetLoadAddress(); + text = CMIUtilString::Format("0x%08x", addr); + const CMIUtilString cString(GetValueCString()); + if (!cString.empty()) + text += CMIUtilString::Format(" %s", cString.c_str()); + } + else + { + const MIchar *pValue = m_bValidSBValue ? m_rValue.GetValue() : nullptr; + text = (pValue != nullptr) ? pValue : m_pUnkwn; + } + + return text; } //++ ------------------------------------------------------------------------------------ -// Details: If the LLDB SB Value object is a char type then form the text data string -// otherwise return nothing. m_bHandleCharType must be true to return text data -// if any. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Text description of the variable's value. -// Throws: None. +// Details: If the LLDB SB Value object is a char type then form the text data string +// otherwise return nothing. m_bHandleCharType must be true to return text data +// if any. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Text description of the variable's value. +// Throws: None. //-- -CMIUtilString CMICmnLLDBUtilSBValue::GetValueCString( void ) const +CMIUtilString +CMICmnLLDBUtilSBValue::GetValueCString(void) const { - CMIUtilString text; - - if( m_bHandleCharType && IsCharType() ) - { - text = ReadCStringFromHostMemory( m_rValue ); - } - - return text; + CMIUtilString text; + + if (m_bHandleCharType && IsCharType()) + { + text = ReadCStringFromHostMemory(m_rValue); + } + + return text; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the flag stating whether this value object is a char type or some -// other type. Char type can be signed or unsigned. -// Type: Method. -// Args: None. -// Return: bool - True = Yes is a char type, false = some other type. -// Throws: None. +// Details: Retrieve the flag stating whether this value object is a char type or some +// other type. Char type can be signed or unsigned. +// Type: Method. +// Args: None. +// Return: bool - True = Yes is a char type, false = some other type. +// Throws: None. //-- -bool CMICmnLLDBUtilSBValue::IsCharType( void ) const +bool +CMICmnLLDBUtilSBValue::IsCharType(void) const { - const MIchar * pName = m_rValue.GetName(); MIunused( pName ); - const lldb::BasicType eType = m_rValue.GetType().GetBasicType(); - return ((eType == lldb::eBasicTypeChar) || - (eType == lldb::eBasicTypeSignedChar) || - (eType == lldb::eBasicTypeUnsignedChar) ); + const MIchar *pName = m_rValue.GetName(); + MIunused(pName); + const lldb::BasicType eType = m_rValue.GetType().GetBasicType(); + return ((eType == lldb::eBasicTypeChar) || (eType == lldb::eBasicTypeSignedChar) || (eType == lldb::eBasicTypeUnsignedChar)); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the flag stating whether any child value object of *this object is a -// char type or some other type. Returns false if there are not children. Char -// type can be signed or unsigned. -// Type: Method. -// Args: None. -// Return: bool - True = Yes is a char type, false = some other type. -// Throws: None. +// Details: Retrieve the flag stating whether any child value object of *this object is a +// char type or some other type. Returns false if there are not children. Char +// type can be signed or unsigned. +// Type: Method. +// Args: None. +// Return: bool - True = Yes is a char type, false = some other type. +// Throws: None. //-- -bool CMICmnLLDBUtilSBValue::IsChildCharType( void ) const +bool +CMICmnLLDBUtilSBValue::IsChildCharType(void) const { - const MIuint nChildren = m_rValue.GetNumChildren(); - - // Is it a basic type - if( nChildren == 0 ) - return false; - - // Is it a composite type - if( nChildren > 1 ) - return false; - - lldb::SBValue member = m_rValue.GetChildAtIndex( 0 ); - const CMICmnLLDBUtilSBValue utilValue( member ); - return utilValue.IsCharType(); + const MIuint nChildren = m_rValue.GetNumChildren(); + + // Is it a basic type + if (nChildren == 0) + return false; + + // Is it a composite type + if (nChildren > 1) + return false; + + lldb::SBValue member = m_rValue.GetChildAtIndex(0); + const CMICmnLLDBUtilSBValue utilValue(member); + return utilValue.IsCharType(); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the C string data for a child of char type (one and only child) for -// the parent value object. If the child is not a char type or the parent has -// more than one child then an empty string is returned. Char type can be -// signed or unsigned. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Text description of the variable's value. -// Throws: None. +// Details: Retrieve the C string data for a child of char type (one and only child) for +// the parent value object. If the child is not a char type or the parent has +// more than one child then an empty string is returned. Char type can be +// signed or unsigned. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Text description of the variable's value. +// Throws: None. //-- -CMIUtilString CMICmnLLDBUtilSBValue::GetChildValueCString( void ) const +CMIUtilString +CMICmnLLDBUtilSBValue::GetChildValueCString(void) const { - CMIUtilString text; - const MIuint nChildren = m_rValue.GetNumChildren(); - - // Is it a basic type - if( nChildren == 0 ) - return text; - - // Is it a composite type - if( nChildren > 1 ) - return text; - - lldb::SBValue member = m_rValue.GetChildAtIndex( 0 ); - const CMICmnLLDBUtilSBValue utilValue( member ); - if( m_bHandleCharType && utilValue.IsCharType() ) - { - text = ReadCStringFromHostMemory( member ); - } - - return text; + CMIUtilString text; + const MIuint nChildren = m_rValue.GetNumChildren(); + + // Is it a basic type + if (nChildren == 0) + return text; + + // Is it a composite type + if (nChildren > 1) + return text; + + lldb::SBValue member = m_rValue.GetChildAtIndex(0); + const CMICmnLLDBUtilSBValue utilValue(member); + if (m_bHandleCharType && utilValue.IsCharType()) + { + text = ReadCStringFromHostMemory(member); + } + + return text; } - + //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the C string data of value object by read the memory where the -// variable is held. -// Type: Method. -// Args: vrValueObj - (R) LLDB SBValue variable object. -// Return: CMIUtilString - Text description of the variable's value. -// Throws: None. +// Details: Retrieve the C string data of value object by read the memory where the +// variable is held. +// Type: Method. +// Args: vrValueObj - (R) LLDB SBValue variable object. +// Return: CMIUtilString - Text description of the variable's value. +// Throws: None. //-- -CMIUtilString CMICmnLLDBUtilSBValue::ReadCStringFromHostMemory( const lldb::SBValue & vrValueObj ) const +CMIUtilString +CMICmnLLDBUtilSBValue::ReadCStringFromHostMemory(const lldb::SBValue &vrValueObj) const { - CMIUtilString text; - - lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValueObj ); - const lldb::addr_t addr = rValue.GetLoadAddress(); - CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); - const MIuint nBytes( 128 ); - const MIchar * pBufferMemory = new MIchar[ nBytes ]; - lldb::SBError error; - const MIuint64 nReadBytes = rSessionInfo.m_lldbProcess.ReadMemory( addr, (void *) pBufferMemory, nBytes, error ); MIunused( nReadBytes ); - text = CMIUtilString::Format( "\\\"%s\\\"", pBufferMemory ); - delete [] pBufferMemory; - - return text; + CMIUtilString text; + + lldb::SBValue &rValue = const_cast(vrValueObj); + const lldb::addr_t addr = rValue.GetLoadAddress(); + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + const MIuint nBytes(128); + const MIchar *pBufferMemory = new MIchar[nBytes]; + lldb::SBError error; + const MIuint64 nReadBytes = rSessionInfo.m_lldbProcess.ReadMemory(addr, (void *)pBufferMemory, nBytes, error); + MIunused(nReadBytes); + text = CMIUtilString::Format("\\\"%s\\\"", pBufferMemory); + delete[] pBufferMemory; + + return text; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the state of the value object's name. -// Type: Method. -// Args: None. -// Return: bool - True = yes name is indeterminate, false = name is valid. -// Throws: None. +// Details: Retrieve the state of the value object's name. +// Type: Method. +// Args: None. +// Return: bool - True = yes name is indeterminate, false = name is valid. +// Throws: None. //-- -bool CMICmnLLDBUtilSBValue::IsNameUnknown( void ) const +bool +CMICmnLLDBUtilSBValue::IsNameUnknown(void) const { - const CMIUtilString name( GetName() ); - return (name == m_pUnkwn); + const CMIUtilString name(GetName()); + return (name == m_pUnkwn); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the state of the value object's value data. -// Type: Method. -// Args: None. -// Return: bool - True = yes value is indeterminate, false = value valid. -// Throws: None. +// Details: Retrieve the state of the value object's value data. +// Type: Method. +// Args: None. +// Return: bool - True = yes value is indeterminate, false = value valid. +// Throws: None. //-- -bool CMICmnLLDBUtilSBValue::IsValueUnknown( void ) const +bool +CMICmnLLDBUtilSBValue::IsValueUnknown(void) const { - const CMIUtilString value( GetValue() ); - return (value == m_pUnkwn); + const CMIUtilString value(GetValue()); + return (value == m_pUnkwn); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the value object's type name if valid. -// Type: Method. -// Args: None. -// Return: CMIUtilString - The type name or "??". -// Throws: None. +// Details: Retrieve the value object's type name if valid. +// Type: Method. +// Args: None. +// Return: CMIUtilString - The type name or "??". +// Throws: None. //-- -CMIUtilString CMICmnLLDBUtilSBValue::GetTypeName( void ) const +CMIUtilString +CMICmnLLDBUtilSBValue::GetTypeName(void) const { - const MIchar * pName = m_bValidSBValue ? m_rValue.GetTypeName() : nullptr; - const CMIUtilString text( (pName != nullptr) ? pName : m_pUnkwn ); - - return text; + const MIchar *pName = m_bValidSBValue ? m_rValue.GetTypeName() : nullptr; + const CMIUtilString text((pName != nullptr) ? pName : m_pUnkwn); + + return text; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the value object's display type name if valid. -// Type: Method. -// Args: None. -// Return: CMIUtilString - The type name or "??". -// Throws: None. +// Details: Retrieve the value object's display type name if valid. +// Type: Method. +// Args: None. +// Return: CMIUtilString - The type name or "??". +// Throws: None. //-- -CMIUtilString CMICmnLLDBUtilSBValue::GetTypeNameDisplay( void ) const +CMIUtilString +CMICmnLLDBUtilSBValue::GetTypeNameDisplay(void) const { - const MIchar * pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr; - const CMIUtilString text( (pName != nullptr) ? pName : m_pUnkwn ); - - return text; + const MIchar *pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr; + const CMIUtilString text((pName != nullptr) ? pName : m_pUnkwn); + + return text; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve whether the value object's is valid or not. -// Type: Method. -// Args: None. -// Return: bool - True = valid, false = not valid. -// Throws: None. +// Details: Retrieve whether the value object's is valid or not. +// Type: Method. +// Args: None. +// Return: bool - True = valid, false = not valid. +// Throws: None. //-- -bool CMICmnLLDBUtilSBValue::IsValid( void ) const +bool +CMICmnLLDBUtilSBValue::IsValid(void) const { - return m_bValidSBValue; + return m_bValidSBValue; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the value object' has a name. A value object can be valid but still -// have no name which suggest it is not a variable. -// Type: Method. -// Args: None. -// Return: bool - True = valid, false = not valid. -// Throws: None. +// Details: Retrieve the value object' has a name. A value object can be valid but still +// have no name which suggest it is not a variable. +// Type: Method. +// Args: None. +// Return: bool - True = valid, false = not valid. +// Throws: None. //-- -bool CMICmnLLDBUtilSBValue::HasName( void ) const +bool +CMICmnLLDBUtilSBValue::HasName(void) const { - bool bHasAName = false; + bool bHasAName = false; - const MIchar * pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr; - if( pName != nullptr ) - { - bHasAName = (CMIUtilString( pName ).length() > 0); - } + const MIchar *pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr; + if (pName != nullptr) + { + bHasAName = (CMIUtilString(pName).length() > 0); + } - return bHasAName; + return bHasAName; } //++ ------------------------------------------------------------------------------------ -// Details: Determine if the value object' respresents a LLDB variable i.e. "$0". -// Type: Method. -// Args: None. -// Return: bool - True = Yes LLDB variable, false = no. -// Throws: None. +// Details: Determine if the value object' respresents a LLDB variable i.e. "$0". +// Type: Method. +// Args: None. +// Return: bool - True = Yes LLDB variable, false = no. +// Throws: None. //-- -bool CMICmnLLDBUtilSBValue::IsLLDBVariable( void ) const +bool +CMICmnLLDBUtilSBValue::IsLLDBVariable(void) const { - return (GetName().at( 0 ) == '$' ); + return (GetName().at(0) == '$'); } - - diff --git a/tools/lldb-mi/MICmnLLDBUtilSBValue.h b/tools/lldb-mi/MICmnLLDBUtilSBValue.h index d2c1876c44b7..1aa3022960b7 100644 --- a/tools/lldb-mi/MICmnLLDBUtilSBValue.h +++ b/tools/lldb-mi/MICmnLLDBUtilSBValue.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLLDBUtilSBValue.h +// File: MICmnLLDBUtilSBValue.h // -// Overview: CMICmnLLDBUtilSBValue interface. +// Overview: CMICmnLLDBUtilSBValue interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -31,41 +31,41 @@ class CMIUtilString; //++ ============================================================================ -// Details: Utility helper class to lldb::SBValue. Using a lldb::SBValue extract -// value object information to help form verbose debug information. -// Gotchas: None. -// Authors: Illya Rudkin 08/07/2014. -// Changes: None. +// Details: Utility helper class to lldb::SBValue. Using a lldb::SBValue extract +// value object information to help form verbose debug information. +// Gotchas: None. +// Authors: Illya Rudkin 08/07/2014. +// Changes: None. //-- class CMICmnLLDBUtilSBValue { -// Methods: -public: - /* ctor */ CMICmnLLDBUtilSBValue( const lldb::SBValue & vrValue, const bool vbHandleCharType = false ); - /* dtor */ ~CMICmnLLDBUtilSBValue( void ); - // - CMIUtilString GetName( void ) const; - CMIUtilString GetValue( void ) const; - CMIUtilString GetValueCString( void ) const; - CMIUtilString GetChildValueCString( void ) const; - CMIUtilString GetTypeName( void ) const; - CMIUtilString GetTypeNameDisplay( void ) const; - bool IsCharType( void ) const; - bool IsChildCharType( void ) const; - bool IsLLDBVariable( void ) const; - bool IsNameUnknown( void ) const; - bool IsValueUnknown( void ) const; - bool IsValid( void ) const; - bool HasName( void ) const; + // Methods: + public: + /* ctor */ CMICmnLLDBUtilSBValue(const lldb::SBValue &vrValue, const bool vbHandleCharType = false); + /* dtor */ ~CMICmnLLDBUtilSBValue(void); + // + CMIUtilString GetName(void) const; + CMIUtilString GetValue(void) const; + CMIUtilString GetValueCString(void) const; + CMIUtilString GetChildValueCString(void) const; + CMIUtilString GetTypeName(void) const; + CMIUtilString GetTypeNameDisplay(void) const; + bool IsCharType(void) const; + bool IsChildCharType(void) const; + bool IsLLDBVariable(void) const; + bool IsNameUnknown(void) const; + bool IsValueUnknown(void) const; + bool IsValid(void) const; + bool HasName(void) const; -// Methods: -private: - CMIUtilString ReadCStringFromHostMemory( const lldb::SBValue & vrValueObj ) const; + // Methods: + private: + CMIUtilString ReadCStringFromHostMemory(const lldb::SBValue &vrValueObj) const; -// Attributes: -private: - lldb::SBValue & m_rValue; - const MIchar * m_pUnkwn; - bool m_bValidSBValue; // True = SBValue is a valid object, false = not valid. - bool m_bHandleCharType; // True = Yes return text molding to char type, false = just return data. + // Attributes: + private: + lldb::SBValue &m_rValue; + const MIchar *m_pUnkwn; + bool m_bValidSBValue; // True = SBValue is a valid object, false = not valid. + bool m_bHandleCharType; // True = Yes return text molding to char type, false = just return data. }; diff --git a/tools/lldb-mi/MICmnLog.cpp b/tools/lldb-mi/MICmnLog.cpp index 4ccbd3ef992c..a18fd2d4e502 100644 --- a/tools/lldb-mi/MICmnLog.cpp +++ b/tools/lldb-mi/MICmnLog.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLog.cpp +// File: MICmnLog.cpp // -// Overview: CMICmnLog implementation. +// Overview: CMICmnLog implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -27,329 +27,344 @@ #include "MIUtilDateTimeStd.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLog constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnLog constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnLog::CMICmnLog( void ) -: m_bEnabled( false ) -, m_bInitializingATM( false ) +CMICmnLog::CMICmnLog(void) + : m_bEnabled(false) + , m_bInitializingATM(false) { - // Do not use this constructor, use Initialize() + // Do not use this constructor, use Initialize() } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLog destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnLog destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnLog::~CMICmnLog( void ) +CMICmnLog::~CMICmnLog(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this Logger. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialize resources for *this Logger. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLog::Initialize( void ) +bool +CMICmnLog::Initialize(void) { - m_clientUsageRefCnt++; - - if( m_bInitialized ) - return MIstatus::success; - - ClrErrorDescription(); - - // Mediums set inside because explicitly initing in MIDriverMain.cpp causes compile errors with CAtlFile - CMICmnLogMediumFile & rFileLog( CMICmnLogMediumFile::Instance() ); - bool bOk = RegisterMedium( rFileLog ); - bOk = bOk && SetEnabled( true ); - if( bOk ) - { - // Set the Log trace file's header - const CMIUtilString & rCR( rFileLog.GetLineReturn() ); - CMIUtilDateTimeStd date; - CMIUtilString msg; - msg = CMIUtilString::Format( "%s\n", CMIDriverMgr::Instance().GetAppVersion().c_str() ); - CMIUtilString logHdr( msg ); - msg = CMIUtilString::Format( MIRSRC( IDS_LOG_MSG_CREATION_DATE ), date.GetDate().c_str(), date.GetTime().c_str(), rCR.c_str() ); - logHdr += msg; - msg = CMIUtilString::Format( MIRSRC( IDS_LOG_MSG_FILE_LOGGER_PATH ), rFileLog.GetFileNamePath().c_str(), rCR.c_str() ); - logHdr += msg; - - bOk = rFileLog.SetHeaderTxt( logHdr ); - - // Note log file medium's status is not available until we write at least once to the file (so just write the title 1st line) - m_bInitializingATM = true; - CMICmnLog::WriteLog( "." ); - if( !rFileLog.IsOk() ) - { - const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LOG_ERR_FILE_LOGGER_DISABLED ), rFileLog.GetErrorDescription().c_str() ) ); - CMICmnLog::WriteLog( msg ); - } - m_bInitializingATM = false; - } - - m_bInitialized = bOk; - - return bOk; + m_clientUsageRefCnt++; + + if (m_bInitialized) + return MIstatus::success; + + ClrErrorDescription(); + + // Mediums set inside because explicitly initing in MIDriverMain.cpp causes compile errors with CAtlFile + CMICmnLogMediumFile &rFileLog(CMICmnLogMediumFile::Instance()); + bool bOk = RegisterMedium(rFileLog); + bOk = bOk && SetEnabled(true); + if (bOk) + { + // Set the Log trace file's header + const CMIUtilString &rCR(rFileLog.GetLineReturn()); + CMIUtilDateTimeStd date; + CMIUtilString msg; + msg = CMIUtilString::Format("%s\n", CMIDriverMgr::Instance().GetAppVersion().c_str()); + CMIUtilString logHdr(msg); + msg = CMIUtilString::Format(MIRSRC(IDS_LOG_MSG_CREATION_DATE), date.GetDate().c_str(), date.GetTime().c_str(), rCR.c_str()); + logHdr += msg; + msg = CMIUtilString::Format(MIRSRC(IDS_LOG_MSG_FILE_LOGGER_PATH), rFileLog.GetFileNamePath().c_str(), rCR.c_str()); + logHdr += msg; + + bOk = rFileLog.SetHeaderTxt(logHdr); + + // Note log file medium's status is not available until we write at least once to the file (so just write the title 1st line) + m_bInitializingATM = true; + CMICmnLog::WriteLog("."); + if (!rFileLog.IsOk()) + { + const CMIUtilString msg( + CMIUtilString::Format(MIRSRC(IDS_LOG_ERR_FILE_LOGGER_DISABLED), rFileLog.GetErrorDescription().c_str())); + CMICmnLog::WriteLog(msg); + } + m_bInitializingATM = false; + } + + m_bInitialized = bOk; + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this Logger. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Release resources for *this Logger. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLog::Shutdown( void ) +bool +CMICmnLog::Shutdown(void) { - if( --m_clientUsageRefCnt > 0 ) - return MIstatus::success; - - if( !m_bInitialized ) - return MIstatus::success; + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - ClrErrorDescription(); + if (!m_bInitialized) + return MIstatus::success; - const bool bOk = UnregisterMediumAll(); - - m_bInitialized = bOk; - - return bOk; -} + ClrErrorDescription(); + + const bool bOk = UnregisterMediumAll(); + + m_bInitialized = bOk; + + return bOk; +} //++ ------------------------------------------------------------------------------------ -// Details: Enabled or disable *this Logger from writing any data to registered clients. -// Type: Method. -// Args: vbYes - (R) True = Logger enabled, false = disabled. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Enabled or disable *this Logger from writing any data to registered clients. +// Type: Method. +// Args: vbYes - (R) True = Logger enabled, false = disabled. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLog::SetEnabled( const bool vbYes ) +bool +CMICmnLog::SetEnabled(const bool vbYes) { - m_bEnabled = vbYes; + m_bEnabled = vbYes; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve state whether *this Logger is enabled writing data to registered clients. -// Type: Method. -// Args: None. -// Return: True = Logger enable. -// False = disabled. -// Throws: None. +// Details: Retrieve state whether *this Logger is enabled writing data to registered clients. +// Type: Method. +// Args: None. +// Return: True = Logger enable. +// False = disabled. +// Throws: None. //-- -bool CMICmnLog::GetEnabled( void ) const +bool +CMICmnLog::GetEnabled(void) const { - return m_bEnabled; + return m_bEnabled; } //++ ------------------------------------------------------------------------------------ -// Details: Unregister all the Mediums registered with *this Logger. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Unregister all the Mediums registered with *this Logger. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLog::UnregisterMediumAll( void ) +bool +CMICmnLog::UnregisterMediumAll(void) { - MapMediumToName_t::const_iterator it = m_mapMediumToName.begin(); - for( ; it != m_mapMediumToName.end( ); it++ ) - { - IMedium * pMedium = (*it).first; - pMedium->Shutdown(); - } - - m_mapMediumToName.clear(); - - return MIstatus::success; + MapMediumToName_t::const_iterator it = m_mapMediumToName.begin(); + for (; it != m_mapMediumToName.end(); it++) + { + IMedium *pMedium = (*it).first; + pMedium->Shutdown(); + } + + m_mapMediumToName.clear(); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Register a Medium with *this Logger. -// Type: Method. -// Args: vrMedium - (R) The medium to register. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Register a Medium with *this Logger. +// Type: Method. +// Args: vrMedium - (R) The medium to register. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLog::RegisterMedium( const IMedium & vrMedium ) +bool +CMICmnLog::RegisterMedium(const IMedium &vrMedium) { - if( HaveMediumAlready( vrMedium ) ) - return MIstatus::success; - - IMedium * pMedium = const_cast< IMedium * >( &vrMedium ); - if( !pMedium->Initialize() ) - { - const CMIUtilString & rStrMedName( pMedium->GetName() ); - const CMIUtilString & rStrMedErr( pMedium->GetError() ); - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LOG_MEDIUM_ERR_INIT ), rStrMedName.c_str(), rStrMedErr.c_str() ) ); - return MIstatus::failure; - } - - MapPairMediumToName_t pr( pMedium, pMedium->GetName() ); - m_mapMediumToName.insert( pr ); - - return MIstatus::success; + if (HaveMediumAlready(vrMedium)) + return MIstatus::success; + + IMedium *pMedium = const_cast(&vrMedium); + if (!pMedium->Initialize()) + { + const CMIUtilString &rStrMedName(pMedium->GetName()); + const CMIUtilString &rStrMedErr(pMedium->GetError()); + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LOG_MEDIUM_ERR_INIT), rStrMedName.c_str(), rStrMedErr.c_str())); + return MIstatus::failure; + } + + MapPairMediumToName_t pr(pMedium, pMedium->GetName()); + m_mapMediumToName.insert(pr); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Query the Logger to see if a medium is already registered. -// Type: Method. -// Args: vrMedium - (R) The medium to query. -// Return: True - registered. -// False - not registered. -// Throws: None. +// Details: Query the Logger to see if a medium is already registered. +// Type: Method. +// Args: vrMedium - (R) The medium to query. +// Return: True - registered. +// False - not registered. +// Throws: None. //-- -bool CMICmnLog::HaveMediumAlready( const IMedium & vrMedium ) const +bool +CMICmnLog::HaveMediumAlready(const IMedium &vrMedium) const { - IMedium * pMedium = const_cast< IMedium * >( &vrMedium ); - const MapMediumToName_t::const_iterator it = m_mapMediumToName.find( pMedium ); - if( it != m_mapMediumToName.end() ) - return true; + IMedium *pMedium = const_cast(&vrMedium); + const MapMediumToName_t::const_iterator it = m_mapMediumToName.find(pMedium); + if (it != m_mapMediumToName.end()) + return true; - return false; + return false; } //++ ------------------------------------------------------------------------------------ -// Details: Unregister a medium from the Logger. -// Type: Method. -// Args: vrMedium - (R) The medium to unregister. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Unregister a medium from the Logger. +// Type: Method. +// Args: vrMedium - (R) The medium to unregister. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLog::UnregisterMedium( const IMedium & vrMedium ) +bool +CMICmnLog::UnregisterMedium(const IMedium &vrMedium) { - IMedium * pMedium = const_cast< IMedium * >( &vrMedium ); - m_mapMediumToName.erase( pMedium ); + IMedium *pMedium = const_cast(&vrMedium); + m_mapMediumToName.erase(pMedium); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: The callee client uses this function to write to the Logger. The data to be -// written is given out to all the mediums registered. The verbosity type parameter -// indicates to the medium(s) the type of data or message given to it. The medium has -// modes of verbosity and depending on the verbosity set determines which writes -// go in to the logger. -// The logger must be initialized successfully before a write to any registered -// can be carried out. -// Type: Method. -// Args: vData - (R) The data to write to the logger. -// veType - (R) Verbosity type. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The callee client uses this function to write to the Logger. The data to be +// written is given out to all the mediums registered. The verbosity type parameter +// indicates to the medium(s) the type of data or message given to it. The medium has +// modes of verbosity and depending on the verbosity set determines which writes +// go in to the logger. +// The logger must be initialized successfully before a write to any registered +// can be carried out. +// Type: Method. +// Args: vData - (R) The data to write to the logger. +// veType - (R) Verbosity type. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLog::Write( const CMIUtilString & vData, const ELogVerbosity veType ) +bool +CMICmnLog::Write(const CMIUtilString &vData, const ELogVerbosity veType) { - if( !m_bInitialized && !m_bInitializingATM ) - return MIstatus::success; - if( m_bRecursiveDive ) - return MIstatus::success; - if( !m_bEnabled ) - return MIstatus::success; - - m_bRecursiveDive = true; - - MIuint cnt = 0; - MIuint cntErr = 0; - { - MapMediumToName_t::const_iterator it = m_mapMediumToName.begin(); - while( it != m_mapMediumToName.end() ) - { - IMedium * pMedium = (*it).first; - const CMIUtilString & rNameMedium = (*it).second; MIunused( rNameMedium ); - if( pMedium->Write( vData, veType ) ) - cnt++; - else - cntErr++; - - // Next - ++it; - } - } - - bool bOk = MIstatus::success; - const MIuint mediumCnt = m_mapMediumToName.size(); - if( (cnt == 0) && (mediumCnt > 0) ) - { - SetErrorDescription( MIRSRC( IDS_LOG_MEDIUM_ERR_WRITE_ANY ) ); - bOk = MIstatus::failure; - } - if( bOk && (cntErr != 0) ) - { - SetErrorDescription( MIRSRC( IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL ) ); - bOk = MIstatus::failure; - } - - m_bRecursiveDive = false; - - return bOk; + if (!m_bInitialized && !m_bInitializingATM) + return MIstatus::success; + if (m_bRecursiveDive) + return MIstatus::success; + if (!m_bEnabled) + return MIstatus::success; + + m_bRecursiveDive = true; + + MIuint cnt = 0; + MIuint cntErr = 0; + { + MapMediumToName_t::const_iterator it = m_mapMediumToName.begin(); + while (it != m_mapMediumToName.end()) + { + IMedium *pMedium = (*it).first; + const CMIUtilString &rNameMedium = (*it).second; + MIunused(rNameMedium); + if (pMedium->Write(vData, veType)) + cnt++; + else + cntErr++; + + // Next + ++it; + } + } + + bool bOk = MIstatus::success; + const MIuint mediumCnt = m_mapMediumToName.size(); + if ((cnt == 0) && (mediumCnt > 0)) + { + SetErrorDescription(MIRSRC(IDS_LOG_MEDIUM_ERR_WRITE_ANY)); + bOk = MIstatus::failure; + } + if (bOk && (cntErr != 0)) + { + SetErrorDescription(MIRSRC(IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL)); + bOk = MIstatus::failure; + } + + m_bRecursiveDive = false; + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Short cut function call to write only to the Log file. -// The logger must be initialized successfully before a write to any registered -// can be carried out. -// Type: Static. -// Args: vData - (R) The data to write to the logger. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Short cut function call to write only to the Log file. +// The logger must be initialized successfully before a write to any registered +// can be carried out. +// Type: Static. +// Args: vData - (R) The data to write to the logger. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLog::WriteLog( const CMIUtilString & vData ) +bool +CMICmnLog::WriteLog(const CMIUtilString &vData) { - return CMICmnLog::Instance().Write( vData, CMICmnLog::eLogVerbosity_Log ); + return CMICmnLog::Instance().Write(vData, CMICmnLog::eLogVerbosity_Log); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve a string detailing the last error. -// Type: Method. -// Args: None, -// Return: CMIUtilString. -// Throws: None. +// Details: Retrieve a string detailing the last error. +// Type: Method. +// Args: None, +// Return: CMIUtilString. +// Throws: None. //-- -const CMIUtilString & CMICmnLog::GetErrorDescription( void ) const +const CMIUtilString & +CMICmnLog::GetErrorDescription(void) const { - return m_strMILastErrorDescription; + return m_strMILastErrorDescription; } //++ ------------------------------------------------------------------------------------ -// Details: Set the internal description of the last error. -// Type: Method. -// Args: (R) String containing a description of the last error. -// Return: None. -// Throws: None. +// Details: Set the internal description of the last error. +// Type: Method. +// Args: (R) String containing a description of the last error. +// Return: None. +// Throws: None. //-- -void CMICmnLog::SetErrorDescription( const CMIUtilString & vrTxt ) const +void +CMICmnLog::SetErrorDescription(const CMIUtilString &vrTxt) const { - m_strMILastErrorDescription = vrTxt; + m_strMILastErrorDescription = vrTxt; } //++ ------------------------------------------------------------------------------------ -// Details: Clear the last error. -// Type: None. -// Args: None. -// Return: None. -// Throws: None. +// Details: Clear the last error. +// Type: None. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMICmnLog::ClrErrorDescription( void ) const +void +CMICmnLog::ClrErrorDescription(void) const { - m_strMILastErrorDescription = CMIUtilString( "" ); + m_strMILastErrorDescription = CMIUtilString(""); } diff --git a/tools/lldb-mi/MICmnLog.h b/tools/lldb-mi/MICmnLog.h index 57288237840d..6884b614896d 100644 --- a/tools/lldb-mi/MICmnLog.h +++ b/tools/lldb-mi/MICmnLog.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLog.h +// File: MICmnLog.h // -// Overview: CMICmnLog interface. +// Overview: CMICmnLog interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -30,114 +30,114 @@ #include "MIUtilSingletonBase.h" //++ ============================================================================ -// Details: MI common code implementation class. Handle application trace -// activity logging. Medium objects derived from the Medium abstract -/// class are registered with this loggor. The function Write is called -// by a client callee to log information. That information is given to -// registered relevant mediums. The medium file is registered during -// *this logs initialization so it will always have a file log for the -// application. -// Singleton class. -// Gotchas: None. -// Authors: Illya Rudkin 01/02/2012. -// Changes: None. +// Details: MI common code implementation class. Handle application trace +// activity logging. Medium objects derived from the Medium abstract +/// class are registered with this loggor. The function Write is called +// by a client callee to log information. That information is given to +// registered relevant mediums. The medium file is registered during +// *this logs initialization so it will always have a file log for the +// application. +// Singleton class. +// Gotchas: None. +// Authors: Illya Rudkin 01/02/2012. +// Changes: None. //-- -class CMICmnLog : public MI::ISingleton< CMICmnLog > +class CMICmnLog : public MI::ISingleton { - friend MI::ISingleton< CMICmnLog >; - -// Enumeration: -public: - //++ - // Description: Data given to the Logger can be of serveral types. The Logger can be - // set at levels of verbosity. Can determine how data is sent to one or - // mediums. - //-- - enum ELogVerbosity - { // Descriptions of what 'may' occur, depends ultimately on the medium itself. See the medium. - eLogVerbosity_FnTrace = 0x00000004, // Debug function stack call tracing - eLogVerbosity_DbgOp = 0x00000008, // Send a string to the debugguer for display (not implemented) - eLogVerbosity_ClientMsg = 0x00000010, // A client using MI can insert messages into the log (not implemented) - eLogVerbosity_Log = 0x00000020 // Send to only the Log file. - }; - -// Class: -public: - //++ - // Description: Register a medium derived from this interface which will be - // called writing log trace data i.e. a file or a console. - // Medium objects registered are not owned by *this logger. - //-- - class IMedium - { - public: - virtual bool Initialize( void ) = 0; - virtual const CMIUtilString & GetName( void ) const = 0; - virtual bool Write( const CMIUtilString & vData, const ELogVerbosity veType ) = 0; - virtual const CMIUtilString & GetError( void ) const = 0; - virtual bool Shutdown( void ) = 0; - - // Not part of the interface, ignore - //AD: This virtual destructor seems to hit a bug in the stdlib - // where vector delete is incorrectly called. Workaround is - // to comment this out while I investigate. - /* dtor */ virtual ~IMedium( void ) {} - }; - -// Statics: -public: - static bool WriteLog( const CMIUtilString & vData ); - -// Methods: -public: - bool RegisterMedium( const IMedium & vrMedium ); - bool UnregisterMedium( const IMedium & vrMedium ); - bool Write( const CMIUtilString & vData, const ELogVerbosity veType ); - bool SetEnabled( const bool vbYes ); - bool GetEnabled( void ) const; - - // MI common object handling - duplicate of CMICmnBase functions, necessary for LINUX build - // Done to stop locking on object construction init circular dependency. - const CMIUtilString & GetErrorDescription( void ) const; - void SetErrorDescription( const CMIUtilString & vrTxt ) const; - void ClrErrorDescription( void ) const; - -// Overridden: -public: - // From MI::ISingleton - virtual bool Initialize( void ); - virtual bool Shutdown( void ); - -// Methods: -private: - /* ctor */ CMICmnLog( void ); - /* ctor */ CMICmnLog( const CMICmnLog & ); - void operator=( const CMICmnLog & ); - -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMICmnLog( void ); - -// Typedef: -private: - typedef std::map< IMedium *, CMIUtilString > MapMediumToName_t; - typedef std::pair< IMedium *, CMIUtilString > MapPairMediumToName_t; - -// Methods: -private: - bool HaveMediumAlready( const IMedium & vrMedium ) const; - bool UnregisterMediumAll( void ); - -// Attributes: -private: - bool m_bRecursiveDive; // True = yes recursive, false = no - MapMediumToName_t m_mapMediumToName; - bool m_bEnabled; // True = Logger enabled for writing to mediums, false = medium not written to - bool m_bInitializingATM; // True = Yes in process of initing *this logger, false = not initing - // - // MI common object handling - duplicate of CMICmnBase functions, necessary for LINUX build - bool m_bInitialized; // True = yes successfully initialized, false = no yet or failed - mutable CMIUtilString m_strMILastErrorDescription; - MIint m_clientUsageRefCnt; // Count of client using *this object so not shutdown() object to early + friend MI::ISingleton; + + // Enumeration: + public: + //++ + // Description: Data given to the Logger can be of serveral types. The Logger can be + // set at levels of verbosity. Can determine how data is sent to one or + // mediums. + //-- + enum ELogVerbosity + { // Descriptions of what 'may' occur, depends ultimately on the medium itself. See the medium. + eLogVerbosity_FnTrace = 0x00000004, // Debug function stack call tracing + eLogVerbosity_DbgOp = 0x00000008, // Send a string to the debugguer for display (not implemented) + eLogVerbosity_ClientMsg = 0x00000010, // A client using MI can insert messages into the log (not implemented) + eLogVerbosity_Log = 0x00000020 // Send to only the Log file. + }; + + // Class: + public: + //++ + // Description: Register a medium derived from this interface which will be + // called writing log trace data i.e. a file or a console. + // Medium objects registered are not owned by *this logger. + //-- + class IMedium + { + public: + virtual bool Initialize(void) = 0; + virtual const CMIUtilString &GetName(void) const = 0; + virtual bool Write(const CMIUtilString &vData, const ELogVerbosity veType) = 0; + virtual const CMIUtilString &GetError(void) const = 0; + virtual bool Shutdown(void) = 0; + + // Not part of the interface, ignore + // AD: This virtual destructor seems to hit a bug in the stdlib + // where vector delete is incorrectly called. Workaround is + // to comment this out while I investigate. + /* dtor */ virtual ~IMedium(void) {} + }; + + // Statics: + public: + static bool WriteLog(const CMIUtilString &vData); + + // Methods: + public: + bool RegisterMedium(const IMedium &vrMedium); + bool UnregisterMedium(const IMedium &vrMedium); + bool Write(const CMIUtilString &vData, const ELogVerbosity veType); + bool SetEnabled(const bool vbYes); + bool GetEnabled(void) const; + + // MI common object handling - duplicate of CMICmnBase functions, necessary for LINUX build + // Done to stop locking on object construction init circular dependency. + const CMIUtilString &GetErrorDescription(void) const; + void SetErrorDescription(const CMIUtilString &vrTxt) const; + void ClrErrorDescription(void) const; + + // Overridden: + public: + // From MI::ISingleton + virtual bool Initialize(void); + virtual bool Shutdown(void); + + // Methods: + private: + /* ctor */ CMICmnLog(void); + /* ctor */ CMICmnLog(const CMICmnLog &); + void operator=(const CMICmnLog &); + + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMICmnLog(void); + + // Typedef: + private: + typedef std::map MapMediumToName_t; + typedef std::pair MapPairMediumToName_t; + + // Methods: + private: + bool HaveMediumAlready(const IMedium &vrMedium) const; + bool UnregisterMediumAll(void); + + // Attributes: + private: + bool m_bRecursiveDive; // True = yes recursive, false = no + MapMediumToName_t m_mapMediumToName; + bool m_bEnabled; // True = Logger enabled for writing to mediums, false = medium not written to + bool m_bInitializingATM; // True = Yes in process of initing *this logger, false = not initing + // + // MI common object handling - duplicate of CMICmnBase functions, necessary for LINUX build + bool m_bInitialized; // True = yes successfully initialized, false = no yet or failed + mutable CMIUtilString m_strMILastErrorDescription; + MIint m_clientUsageRefCnt; // Count of client using *this object so not shutdown() object to early }; diff --git a/tools/lldb-mi/MICmnLogMediumFile.cpp b/tools/lldb-mi/MICmnLogMediumFile.cpp index 228a9cf4b3be..add4426b9352 100644 --- a/tools/lldb-mi/MICmnLogMediumFile.cpp +++ b/tools/lldb-mi/MICmnLogMediumFile.cpp @@ -8,413 +8,433 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLogMediumFile.cpp +// File: MICmnLogMediumFile.cpp // -// Overview: CMICmnLogMediumFile implementation. +// Overview: CMICmnLogMediumFile implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: #include "MICmnLogMediumFile.h" #include "MICmnResources.h" -#if defined( _MSC_VER ) - #include "MIUtilSystemWindows.h" -#elif defined( __FreeBSD__ ) || defined( __linux__ ) - #include "MIUtilSystemLinux.h" -#elif defined( __APPLE__ ) - #include "MIUtilSystemOsx.h" +#if defined(_MSC_VER) +#include "MIUtilSystemWindows.h" +#elif defined(__FreeBSD__) || defined(__linux__) +#include "MIUtilSystemLinux.h" +#elif defined(__APPLE__) +#include "MIUtilSystemOsx.h" #endif // defined( _MSC_VER ) //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLogMediumFile constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnLogMediumFile constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnLogMediumFile::CMICmnLogMediumFile( void ) -: m_constThisMediumName( MIRSRC( IDS_MEDIUMFILE_NAME ) ) -, m_constMediumFileName( "lldb-mi-log.txt" ) -, m_fileNamePath( MIRSRC( IDS_MEDIUMFILE_ERR_INVALID_PATH ) ) -, m_eVerbosityType( CMICmnLog::eLogVerbosity_Log ) -, m_strDate( CMIUtilDateTimeStd().GetDate() ) -, m_fileHeaderTxt( MIRSRC( IDS_MEDIUMFILE_ERR_FILE_HEADER ) ) +CMICmnLogMediumFile::CMICmnLogMediumFile(void) + : m_constThisMediumName(MIRSRC(IDS_MEDIUMFILE_NAME)) + , m_constMediumFileName("lldb-mi-log.txt") + , m_fileNamePath(MIRSRC(IDS_MEDIUMFILE_ERR_INVALID_PATH)) + , m_eVerbosityType(CMICmnLog::eLogVerbosity_Log) + , m_strDate(CMIUtilDateTimeStd().GetDate()) + , m_fileHeaderTxt(MIRSRC(IDS_MEDIUMFILE_ERR_FILE_HEADER)) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnLogMediumFile destructor. -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnLogMediumFile destructor. +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnLogMediumFile::~CMICmnLogMediumFile( void ) +CMICmnLogMediumFile::~CMICmnLogMediumFile(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Get the singleton instance of *this class. -// Type: Static. -// Args: None. -// Return: CMICmnLogMediumFile - Reference to *this object. -// Throws: None. +// Details: Get the singleton instance of *this class. +// Type: Static. +// Args: None. +// Return: CMICmnLogMediumFile - Reference to *this object. +// Throws: None. //-- -CMICmnLogMediumFile & CMICmnLogMediumFile::Instance( void ) +CMICmnLogMediumFile & +CMICmnLogMediumFile::Instance(void) { - static CMICmnLogMediumFile instance; + static CMICmnLogMediumFile instance; - return instance; + return instance; } //++ ------------------------------------------------------------------------------------ -// Details: Initialize setup *this medium ready for use. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialize setup *this medium ready for use. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLogMediumFile::Initialize( void ) +bool +CMICmnLogMediumFile::Initialize(void) { - m_bInitialized = FileFormFileNamePath(); - - return m_bInitialized; + m_bInitialized = FileFormFileNamePath(); + + return m_bInitialized; } //++ ------------------------------------------------------------------------------------ -// Details: Unbind detach or release resources used by *this medium. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: Unbind detach or release resources used by *this medium. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -bool CMICmnLogMediumFile::Shutdown( void ) +bool +CMICmnLogMediumFile::Shutdown(void) { - if( m_bInitialized ) - { - m_bInitialized = false; - m_file.Close(); - } - return MIstatus::success; + if (m_bInitialized) + { + m_bInitialized = false; + m_file.Close(); + } + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the name of *this medium. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString - Text data. -// Throws: None. +// Details: Retrieve the name of *this medium. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString - Text data. +// Throws: None. //-- -const CMIUtilString & CMICmnLogMediumFile::GetName( void ) const +const CMIUtilString & +CMICmnLogMediumFile::GetName(void) const { - return m_constThisMediumName; + return m_constThisMediumName; } //++ ------------------------------------------------------------------------------------ -// Details: The callee client calls the write function on the Logger. The data to be -// written is given out to all the mediums registered. The verbosity type parameter -// indicates to the medium the type of data or message given to it. The medium has -// modes of verbosity and depending on the verbosity set determines which data is -// sent to the medium's output. -// Type: Method. -// Args: vData - (R) The data to write to the logger. -// veType - (R) Verbosity type. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The callee client calls the write function on the Logger. The data to be +// written is given out to all the mediums registered. The verbosity type parameter +// indicates to the medium the type of data or message given to it. The medium has +// modes of verbosity and depending on the verbosity set determines which data is +// sent to the medium's output. +// Type: Method. +// Args: vData - (R) The data to write to the logger. +// veType - (R) Verbosity type. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLogMediumFile::Write( const CMIUtilString & vData, const CMICmnLog::ELogVerbosity veType ) +bool +CMICmnLogMediumFile::Write(const CMIUtilString &vData, const CMICmnLog::ELogVerbosity veType) { - if( m_bInitialized && m_file.IsOk() ) - { - const bool bDoWrite = (m_eVerbosityType & veType); - if( bDoWrite ) - { - bool bNewCreated = false; - bool bOk = m_file.CreateWrite( m_fileNamePath, bNewCreated ); - if( bOk ) - { - if( bNewCreated ) - bOk = FileWriteHeader(); - bOk = bOk && FileWriteEnglish( MassagedData( vData, veType ) ); - } - return bOk; - } - } - - return MIstatus::failure; + if (m_bInitialized && m_file.IsOk()) + { + const bool bDoWrite = (m_eVerbosityType & veType); + if (bDoWrite) + { + bool bNewCreated = false; + bool bOk = m_file.CreateWrite(m_fileNamePath, bNewCreated); + if (bOk) + { + if (bNewCreated) + bOk = FileWriteHeader(); + bOk = bOk && FileWriteEnglish(MassagedData(vData, veType)); + } + return bOk; + } + } + + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve *this medium's last error condition. -// Type: Method. -// Args: None. -// Return: CString & - Text description. -// Throws: None. +// Details: Retrieve *this medium's last error condition. +// Type: Method. +// Args: None. +// Return: CString & - Text description. +// Throws: None. //-- -const CMIUtilString & CMICmnLogMediumFile::GetError( void ) const +const CMIUtilString & +CMICmnLogMediumFile::GetError(void) const { - return m_strMILastErrorDescription; + return m_strMILastErrorDescription; } //++ ------------------------------------------------------------------------------------ -// Details: Set the verbosity mode for this medium. -// Type: Method. -// Args: veType - (R) Mask value. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Set the verbosity mode for this medium. +// Type: Method. +// Args: veType - (R) Mask value. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLogMediumFile::SetVerbosity( const MIuint veType ) +bool +CMICmnLogMediumFile::SetVerbosity(const MIuint veType) { - m_eVerbosityType = veType; - return MIstatus::success; + m_eVerbosityType = veType; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Get the verbosity mode for this medium. -// Type: Method. -// Args: veType - (R) Mask value. -// Return: CMICmnLog::ELogVerbosity - Mask value. -// Throws: None. +// Details: Get the verbosity mode for this medium. +// Type: Method. +// Args: veType - (R) Mask value. +// Return: CMICmnLog::ELogVerbosity - Mask value. +// Throws: None. //-- -MIuint CMICmnLogMediumFile::GetVerbosity( void ) const +MIuint +CMICmnLogMediumFile::GetVerbosity(void) const { - return m_eVerbosityType; + return m_eVerbosityType; } //++ ------------------------------------------------------------------------------------ -// Details: Write data to a file English font. -// Type: Method. -// Args: vData - (R) The data to write to the logger. -// Return: None. -// Throws: None. +// Details: Write data to a file English font. +// Type: Method. +// Args: vData - (R) The data to write to the logger. +// Return: None. +// Throws: None. //-- -bool CMICmnLogMediumFile::FileWriteEnglish( const CMIUtilString & vData ) +bool +CMICmnLogMediumFile::FileWriteEnglish(const CMIUtilString &vData) { - return m_file.Write( vData ); + return m_file.Write(vData); } //++ ------------------------------------------------------------------------------------ -// Details: Determine and form the medium file's directory path and name. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Determine and form the medium file's directory path and name. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLogMediumFile::FileFormFileNamePath( void ) +bool +CMICmnLogMediumFile::FileFormFileNamePath(void) { - ClrErrorDescription(); - - m_fileNamePath = MIRSRC( IDS_MEDIUMFILE_ERR_INVALID_PATH ); - - CMIUtilString strPathName; - if( CMIUtilSystem().GetLogFilesPath( strPathName ) ) - { - const CMIUtilString strPath = CMIUtilFileStd().StripOffFileName( strPathName ); - - // ToDo: Review this LINUX log file quick fix so not hidden - // AD: - // Linux was creating a log file here called '.\log.txt'. The '.' on linux - // signifies that this file is 'hidden' and not normally visible. A quick fix - // is to remove the path component all together. Linux also normally uses '/' - // as directory separators, again leading to the problem of the hidden log. -#if defined ( _MSC_VER ) - m_fileNamePath = CMIUtilString::Format( "%s\\%s", strPath.c_str(), m_constMediumFileName.c_str() ); + ClrErrorDescription(); + + m_fileNamePath = MIRSRC(IDS_MEDIUMFILE_ERR_INVALID_PATH); + + CMIUtilString strPathName; + if (CMIUtilSystem().GetLogFilesPath(strPathName)) + { + const CMIUtilString strPath = CMIUtilFileStd().StripOffFileName(strPathName); + +// ToDo: Review this LINUX log file quick fix so not hidden +// AD: +// Linux was creating a log file here called '.\log.txt'. The '.' on linux +// signifies that this file is 'hidden' and not normally visible. A quick fix +// is to remove the path component all together. Linux also normally uses '/' +// as directory separators, again leading to the problem of the hidden log. +#if defined(_MSC_VER) + m_fileNamePath = CMIUtilString::Format("%s\\%s", strPath.c_str(), m_constMediumFileName.c_str()); #else - m_fileNamePath = CMIUtilString::Format( "%s", m_constMediumFileName.c_str() ); + m_fileNamePath = CMIUtilString::Format("%s", m_constMediumFileName.c_str()); #endif // defined ( _MSC_VER ) - return MIstatus::success; - } + return MIstatus::success; + } + + SetErrorDescription(MIRSRC(IDE_MEDIUMFILE_ERR_GET_FILE_PATHNAME_SYS)); - SetErrorDescription( MIRSRC( IDE_MEDIUMFILE_ERR_GET_FILE_PATHNAME_SYS ) ); - - return MIstatus::failure; + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the medium file's directory path and name. -// Type: Method. -// Args: None. -// Return: CMIUtilString & - File path. -// Throws: None. +// Details: Retrieve the medium file's directory path and name. +// Type: Method. +// Args: None. +// Return: CMIUtilString & - File path. +// Throws: None. //-- -const CMIUtilString & CMICmnLogMediumFile::GetFileNamePath( void ) const +const CMIUtilString & +CMICmnLogMediumFile::GetFileNamePath(void) const { - return m_fileNamePath; + return m_fileNamePath; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the medium file's name. -// Type: Method. -// Args: None. -// Return: CMIUtilString & - File name. -// Throws: None. +// Details: Retrieve the medium file's name. +// Type: Method. +// Args: None. +// Return: CMIUtilString & - File name. +// Throws: None. //-- -const CMIUtilString & CMICmnLogMediumFile::GetFileName( void ) const +const CMIUtilString & +CMICmnLogMediumFile::GetFileName(void) const { - return m_constMediumFileName; + return m_constMediumFileName; } //++ ------------------------------------------------------------------------------------ -// Details: Massage the data to behave correct when submitted to file. Insert extra log -// specific text. The veType is there to allow in the future to parse the log and -// filter in out specific types of message to make viewing the log more manageable. -// Type: Method. -// Args: vData - (R) Raw data. -// veType - (R) Message type. -// Return: CMIUtilString - Massaged data. -// Throws: None. +// Details: Massage the data to behave correct when submitted to file. Insert extra log +// specific text. The veType is there to allow in the future to parse the log and +// filter in out specific types of message to make viewing the log more manageable. +// Type: Method. +// Args: vData - (R) Raw data. +// veType - (R) Message type. +// Return: CMIUtilString - Massaged data. +// Throws: None. //-- -CMIUtilString CMICmnLogMediumFile::MassagedData( const CMIUtilString & vData, const CMICmnLog::ELogVerbosity veType ) +CMIUtilString +CMICmnLogMediumFile::MassagedData(const CMIUtilString &vData, const CMICmnLog::ELogVerbosity veType) { - const CMIUtilString strCr( "\n" ); - CMIUtilString data; - const MIchar verbosityCode( ConvertLogVerbosityTypeToId( veType ) ); - const CMIUtilString dt( CMIUtilString::Format( "%s %s", m_strDate.c_str(), m_dateTime.GetTime().c_str() ) ); - - data = CMIUtilString::Format( "%c,%s,%s", verbosityCode, dt.c_str(), vData.c_str() ); - data = ConvertCr( data ); - - // Look for EOL... - const MIint pos = vData.rfind( strCr ); - if( pos == (MIint) vData.size() ) - return data; - - // ... did not have an EOL so add one - data += GetLineReturn(); - - return data; + const CMIUtilString strCr("\n"); + CMIUtilString data; + const MIchar verbosityCode(ConvertLogVerbosityTypeToId(veType)); + const CMIUtilString dt(CMIUtilString::Format("%s %s", m_strDate.c_str(), m_dateTime.GetTime().c_str())); + + data = CMIUtilString::Format("%c,%s,%s", verbosityCode, dt.c_str(), vData.c_str()); + data = ConvertCr(data); + + // Look for EOL... + const MIint pos = vData.rfind(strCr); + if (pos == (MIint)vData.size()) + return data; + + // ... did not have an EOL so add one + data += GetLineReturn(); + + return data; } //++ ------------------------------------------------------------------------------------ -// Details: Convert the Log's verbosity type number into a single char character. -// Type: Method. -// Args: veType - (R) Message type. -// Return: wchar_t - A letter. -// Throws: None. +// Details: Convert the Log's verbosity type number into a single char character. +// Type: Method. +// Args: veType - (R) Message type. +// Return: wchar_t - A letter. +// Throws: None. //-- -MIchar CMICmnLogMediumFile::ConvertLogVerbosityTypeToId( const CMICmnLog::ELogVerbosity veType ) const +MIchar +CMICmnLogMediumFile::ConvertLogVerbosityTypeToId(const CMICmnLog::ELogVerbosity veType) const { - MIchar c = 0; - if( veType != 0 ) - { - MIuint cnt = 0; - MIuint number( veType ); - while( 1 != number ) - { - number = number >> 1; - ++cnt; - } - c = 'A' + cnt; - } - else - { - c = '*'; - } - - return c; + MIchar c = 0; + if (veType != 0) + { + MIuint cnt = 0; + MIuint number(veType); + while (1 != number) + { + number = number >> 1; + ++cnt; + } + c = 'A' + cnt; + } + else + { + c = '*'; + } + + return c; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve state of whether the file medium is ok. -// Type: Method. -// Args: None. -// Return: True - file ok. -// False - file has a problem. -// Throws: None. +// Details: Retrieve state of whether the file medium is ok. +// Type: Method. +// Args: None. +// Return: True - file ok. +// False - file has a problem. +// Throws: None. //-- -bool CMICmnLogMediumFile::IsOk( void ) const +bool +CMICmnLogMediumFile::IsOk(void) const { - return m_file.IsOk(); + return m_file.IsOk(); } //++ ------------------------------------------------------------------------------------ -// Details: Status on the file log medium existing already. -// Type: Method. -// Args: None. -// Return: True - Exists. -// False - Not found. -// Throws: None. +// Details: Status on the file log medium existing already. +// Type: Method. +// Args: None. +// Return: True - Exists. +// False - Not found. +// Throws: None. //-- -bool CMICmnLogMediumFile::IsFileExist( void ) const +bool +CMICmnLogMediumFile::IsFileExist(void) const { - return m_file.IsFileExist( GetFileNamePath() ); + return m_file.IsFileExist(GetFileNamePath()); } //++ ------------------------------------------------------------------------------------ -// Details: Write the header text the logger file. -// Type: Method. -// Args: vText - (R) Text. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Write the header text the logger file. +// Type: Method. +// Args: vText - (R) Text. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLogMediumFile::FileWriteHeader( void ) +bool +CMICmnLogMediumFile::FileWriteHeader(void) { - return FileWriteEnglish( ConvertCr( m_fileHeaderTxt ) ); + return FileWriteEnglish(ConvertCr(m_fileHeaderTxt)); } //++ ------------------------------------------------------------------------------------ -// Details: Convert any carriage line returns to be compatible with the platform the -// Log fiel is being written to. -// Type: Method. -// Args: vData - (R) Text data. -// Return: CMIUtilString - Converted string data. -// Throws: None. +// Details: Convert any carriage line returns to be compatible with the platform the +// Log fiel is being written to. +// Type: Method. +// Args: vData - (R) Text data. +// Return: CMIUtilString - Converted string data. +// Throws: None. //-- -CMIUtilString CMICmnLogMediumFile::ConvertCr( const CMIUtilString & vData ) const +CMIUtilString +CMICmnLogMediumFile::ConvertCr(const CMIUtilString &vData) const { - const CMIUtilString strCr( "\n" ); - const CMIUtilString & rCrCmpat( GetLineReturn() ); - - if( strCr == rCrCmpat ) - return vData; - - const MIuint nSizeCmpat( rCrCmpat.size() ); - const MIuint nSize( strCr.size() ); - CMIUtilString strConv( vData ); - MIint pos = strConv.find( strCr ); - while( pos != (MIint) CMIUtilString::npos ) - { - strConv.replace( pos, nSize, rCrCmpat ); - pos = strConv.find( strCr, pos + nSizeCmpat ); - } - - return strConv; + const CMIUtilString strCr("\n"); + const CMIUtilString &rCrCmpat(GetLineReturn()); + + if (strCr == rCrCmpat) + return vData; + + const MIuint nSizeCmpat(rCrCmpat.size()); + const MIuint nSize(strCr.size()); + CMIUtilString strConv(vData); + MIint pos = strConv.find(strCr); + while (pos != (MIint)CMIUtilString::npos) + { + strConv.replace(pos, nSize, rCrCmpat); + pos = strConv.find(strCr, pos + nSizeCmpat); + } + + return strConv; } //++ ------------------------------------------------------------------------------------ -// Details: Set the header text that is written to the logger file at the begining. -// Type: Method. -// Args: vText - (R) Text. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Set the header text that is written to the logger file at the begining. +// Type: Method. +// Args: vText - (R) Text. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnLogMediumFile::SetHeaderTxt( const CMIUtilString & vText ) +bool +CMICmnLogMediumFile::SetHeaderTxt(const CMIUtilString &vText) { - m_fileHeaderTxt = vText; + m_fileHeaderTxt = vText; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the file current carriage line return characters used. -// Type: Method. -// Args: None. -// Return: CMIUtilString & - Text. -// Throws: None. +// Details: Retrieve the file current carriage line return characters used. +// Type: Method. +// Args: None. +// Return: CMIUtilString & - Text. +// Throws: None. //-- -const CMIUtilString & CMICmnLogMediumFile::GetLineReturn( void ) const +const CMIUtilString & +CMICmnLogMediumFile::GetLineReturn(void) const { - return m_file.GetLineReturn(); + return m_file.GetLineReturn(); } diff --git a/tools/lldb-mi/MICmnLogMediumFile.h b/tools/lldb-mi/MICmnLogMediumFile.h index affe24e09e57..8496320db678 100644 --- a/tools/lldb-mi/MICmnLogMediumFile.h +++ b/tools/lldb-mi/MICmnLogMediumFile.h @@ -8,89 +8,87 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnLogMediumFile.h +// File: MICmnLogMediumFile.h // -// Overview: CMICmnLogMediumFile interface. +// Overview: CMICmnLogMediumFile interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once // In-house headers: #include "MIUtilFileStd.h" -#include "MIUtilString.h" +#include "MIUtilString.h" #include "MICmnBase.h" #include "MICmnLog.h" #include "MIUtilDateTimeStd.h" //++ ============================================================================ -// Details: MI common code implementation class. Logs application fn trace/message/ -// error messages to a file. Used as part of the CMICmnLog Logger -// system. When instantiated *this object is register with the Logger -// which the Logger when given data to write to registered medium comes -// *this medium. -// Singleton class. -// Gotchas: None. -// Authors: Illya Rudkin 30/01/2014. -// Changes: None. +// Details: MI common code implementation class. Logs application fn trace/message/ +// error messages to a file. Used as part of the CMICmnLog Logger +// system. When instantiated *this object is register with the Logger +// which the Logger when given data to write to registered medium comes +// *this medium. +// Singleton class. +// Gotchas: None. +// Authors: Illya Rudkin 30/01/2014. +// Changes: None. //-- -class CMICmnLogMediumFile -: public CMICmnBase -, public CMICmnLog::IMedium +class CMICmnLogMediumFile : public CMICmnBase, public CMICmnLog::IMedium { -// Statics: -public: - static CMICmnLogMediumFile & Instance( void ); + // Statics: + public: + static CMICmnLogMediumFile &Instance(void); -// Methods: -public: - bool SetHeaderTxt( const CMIUtilString & vText ); - bool SetVerbosity( const MIuint veType ); - MIuint GetVerbosity( void ) const; - const CMIUtilString & GetFileName( void ) const; - const CMIUtilString & GetFileNamePath( void ) const; - bool IsOk( void ) const; - bool IsFileExist( void ) const; - const CMIUtilString & GetLineReturn( void ) const; + // Methods: + public: + bool SetHeaderTxt(const CMIUtilString &vText); + bool SetVerbosity(const MIuint veType); + MIuint GetVerbosity(void) const; + const CMIUtilString &GetFileName(void) const; + const CMIUtilString &GetFileNamePath(void) const; + bool IsOk(void) const; + bool IsFileExist(void) const; + const CMIUtilString &GetLineReturn(void) const; -// Overridden: -public: - // From CMICmnBase - /* dtor */ virtual ~CMICmnLogMediumFile( void ); - // From CMICmnLog::IMedium - virtual bool Initialize( void ); - virtual const CMIUtilString & GetName( void ) const; - virtual bool Write( const CMIUtilString & vData, const CMICmnLog::ELogVerbosity veType ); - virtual const CMIUtilString & GetError( void ) const; - virtual bool Shutdown( void ); + // Overridden: + public: + // From CMICmnBase + /* dtor */ virtual ~CMICmnLogMediumFile(void); + // From CMICmnLog::IMedium + virtual bool Initialize(void); + virtual const CMIUtilString &GetName(void) const; + virtual bool Write(const CMIUtilString &vData, const CMICmnLog::ELogVerbosity veType); + virtual const CMIUtilString &GetError(void) const; + virtual bool Shutdown(void); -// Methods: -private: - /* ctor */ CMICmnLogMediumFile( void ); - /* ctor */ CMICmnLogMediumFile( const CMICmnLogMediumFile & ); - void operator=( const CMICmnLogMediumFile & ); - - bool FileWriteEnglish( const CMIUtilString & vData ); - bool FileFormFileNamePath( void ); - CMIUtilString MassagedData( const CMIUtilString & vData, const CMICmnLog::ELogVerbosity veType ); - bool FileWriteHeader( void ); - MIchar ConvertLogVerbosityTypeToId( const CMICmnLog::ELogVerbosity veType ) const; - CMIUtilString ConvertCr( const CMIUtilString & vData ) const; + // Methods: + private: + /* ctor */ CMICmnLogMediumFile(void); + /* ctor */ CMICmnLogMediumFile(const CMICmnLogMediumFile &); + void operator=(const CMICmnLogMediumFile &); -// Attributes: -private: - const CMIUtilString m_constThisMediumName; - const CMIUtilString m_constMediumFileName; - // - CMIUtilString m_fileNamePath; - MIuint m_eVerbosityType; - CMIUtilString m_strDate; - CMIUtilString m_fileHeaderTxt; - CMIUtilFileStd m_file; - CMIUtilDateTimeStd m_dateTime; + bool FileWriteEnglish(const CMIUtilString &vData); + bool FileFormFileNamePath(void); + CMIUtilString MassagedData(const CMIUtilString &vData, const CMICmnLog::ELogVerbosity veType); + bool FileWriteHeader(void); + MIchar ConvertLogVerbosityTypeToId(const CMICmnLog::ELogVerbosity veType) const; + CMIUtilString ConvertCr(const CMIUtilString &vData) const; + + // Attributes: + private: + const CMIUtilString m_constThisMediumName; + const CMIUtilString m_constMediumFileName; + // + CMIUtilString m_fileNamePath; + MIuint m_eVerbosityType; + CMIUtilString m_strDate; + CMIUtilString m_fileHeaderTxt; + CMIUtilFileStd m_file; + CMIUtilDateTimeStd m_dateTime; }; diff --git a/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp b/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp index c3826f01ae85..2977753038a6 100644 --- a/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp +++ b/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnMIOutOfBandRecord.h +// File: MICmnMIOutOfBandRecord.h // -// Overview: CMICmnMIOutOfBandRecord implementation. +// Overview: CMICmnMIOutOfBandRecord implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -24,138 +24,136 @@ #include "MICmnResources.h" // Instantiations: -CMICmnMIOutOfBandRecord::MapOutOfBandToOutOfBandText_t ms_MapOutOfBandToOutOfBandText = -{ - { CMICmnMIOutOfBandRecord::eOutOfBand_Running, "running" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, "stopped" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, "breakpoint-created" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, "breakpoint-modified" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_Thread, "" }, // "" Meant to be empty - { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupAdded, "thread-group-added" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, "thread-group-exited" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupRemoved, "thread-group-removed" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, "thread-group-started" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, "thread-created" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, "thread-exited" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, "thread-selected" } -}; -CMICmnMIOutOfBandRecord::MapOutOfBandToOutOfBandText_t ms_constMapAsyncRecordTextToToken = -{ - { CMICmnMIOutOfBandRecord::eOutOfBand_Running, "*" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, "*" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, "=" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, "=" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_Thread, "@" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupAdded, "=" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, "=" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupRemoved, "=" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, "=" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, "=" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, "=" }, - { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, "=" } -}; - +CMICmnMIOutOfBandRecord::MapOutOfBandToOutOfBandText_t ms_MapOutOfBandToOutOfBandText = { + {CMICmnMIOutOfBandRecord::eOutOfBand_Running, "running"}, + {CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, "stopped"}, + {CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, "breakpoint-created"}, + {CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, "breakpoint-modified"}, + {CMICmnMIOutOfBandRecord::eOutOfBand_Thread, ""}, // "" Meant to be empty + {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupAdded, "thread-group-added"}, + {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, "thread-group-exited"}, + {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupRemoved, "thread-group-removed"}, + {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, "thread-group-started"}, + {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, "thread-created"}, + {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, "thread-exited"}, + {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, "thread-selected"}}; +CMICmnMIOutOfBandRecord::MapOutOfBandToOutOfBandText_t ms_constMapAsyncRecordTextToToken = { + {CMICmnMIOutOfBandRecord::eOutOfBand_Running, "*"}, + {CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, "*"}, + {CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, "="}, + {CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, "="}, + {CMICmnMIOutOfBandRecord::eOutOfBand_Thread, "@"}, + {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupAdded, "="}, + {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, "="}, + {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupRemoved, "="}, + {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, "="}, + {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, "="}, + {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, "="}, + {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, "="}}; + //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIOutOfBandRecord constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnMIOutOfBandRecord constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord( void ) -: m_strAsyncRecord( MIRSRC( IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION ) ) +CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(void) + : m_strAsyncRecord(MIRSRC(IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION)) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIOutOfBandRecord constructor. -// Type: Method. -// Args: veType - (R) A MI Out-of-Bound enumeration. -// Return: None. -// Throws: None. +// Details: CMICmnMIOutOfBandRecord constructor. +// Type: Method. +// Args: veType - (R) A MI Out-of-Bound enumeration. +// Return: None. +// Throws: None. //-- -CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord( const OutOfBand_e veType ) -: m_eResultAsyncRecordClass( veType ) -, m_strAsyncRecord( MIRSRC( IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION ) ) +CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(const OutOfBand_e veType) + : m_eResultAsyncRecordClass(veType) + , m_strAsyncRecord(MIRSRC(IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION)) { - BuildAsyncRecord(); + BuildAsyncRecord(); } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIOutOfBandRecord constructor. -// Type: Method. -// Args: veType - (R) A MI Out-of-Bound enumeration. -// vMIResult - (R) A MI result object. -// Return: None. -// Throws: None. +// Details: CMICmnMIOutOfBandRecord constructor. +// Type: Method. +// Args: veType - (R) A MI Out-of-Bound enumeration. +// vMIResult - (R) A MI result object. +// Return: None. +// Throws: None. //-- -CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord( const OutOfBand_e veType, const CMICmnMIValueResult & vValue ) -: m_eResultAsyncRecordClass( veType ) -, m_strAsyncRecord( MIRSRC( IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION ) ) -, m_partResult( vValue ) +CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(const OutOfBand_e veType, const CMICmnMIValueResult &vValue) + : m_eResultAsyncRecordClass(veType) + , m_strAsyncRecord(MIRSRC(IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION)) + , m_partResult(vValue) { - BuildAsyncRecord(); - Add( m_partResult ); + BuildAsyncRecord(); + Add(m_partResult); } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIOutOfBandRecord destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnMIOutOfBandRecord destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnMIOutOfBandRecord::~CMICmnMIOutOfBandRecord( void ) +CMICmnMIOutOfBandRecord::~CMICmnMIOutOfBandRecord(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Return the MI Out-of-band record as a string. The string is a direct result of -// work done on *this Out-of-band record so if not enough data is added then it is -// possible to return a malformed Out-of-band record. If nothing has been set or -// added to *this MI Out-of-band record object then text "" will be returned. -// Type: Method. -// Args: None. -// Return: CMIUtilString & - MI output text. -// Throws: None. +// Details: Return the MI Out-of-band record as a string. The string is a direct result of +// work done on *this Out-of-band record so if not enough data is added then it is +// possible to return a malformed Out-of-band record. If nothing has been set or +// added to *this MI Out-of-band record object then text "" will be returned. +// Type: Method. +// Args: None. +// Return: CMIUtilString & - MI output text. +// Throws: None. //-- -const CMIUtilString & CMICmnMIOutOfBandRecord::GetString( void ) const +const CMIUtilString & +CMICmnMIOutOfBandRecord::GetString(void) const { - return m_strAsyncRecord; + return m_strAsyncRecord; } - + //++ ------------------------------------------------------------------------------------ -// Details: Build the Out-of-band record's mandatory data part. The part up to the first -// (additional) result i.e. async-record ==> "*" type. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Build the Out-of-band record's mandatory data part. The part up to the first +// (additional) result i.e. async-record ==> "*" type. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIOutOfBandRecord::BuildAsyncRecord( void ) +bool +CMICmnMIOutOfBandRecord::BuildAsyncRecord(void) { - const MIchar * pFormat = "%s%s"; - const CMIUtilString & rStrAsyncRecord( ms_MapOutOfBandToOutOfBandText[ m_eResultAsyncRecordClass ] ); - const CMIUtilString & rStrToken( ms_constMapAsyncRecordTextToToken[ m_eResultAsyncRecordClass ] ); - m_strAsyncRecord = CMIUtilString::Format( pFormat, rStrToken.c_str(), rStrAsyncRecord.c_str() ); + const MIchar *pFormat = "%s%s"; + const CMIUtilString &rStrAsyncRecord(ms_MapOutOfBandToOutOfBandText[m_eResultAsyncRecordClass]); + const CMIUtilString &rStrToken(ms_constMapAsyncRecordTextToToken[m_eResultAsyncRecordClass]); + m_strAsyncRecord = CMIUtilString::Format(pFormat, rStrToken.c_str(), rStrAsyncRecord.c_str()); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Add to *this Out-of-band record additional information. -// Type: Method. -// Args: vMIValue - (R) A MI value derived object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Add to *this Out-of-band record additional information. +// Type: Method. +// Args: vMIValue - (R) A MI value derived object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIOutOfBandRecord::Add( const CMICmnMIValue & vMIValue ) +bool +CMICmnMIOutOfBandRecord::Add(const CMICmnMIValue &vMIValue) { - m_strAsyncRecord += ","; - m_strAsyncRecord += vMIValue.GetString(); + m_strAsyncRecord += ","; + m_strAsyncRecord += vMIValue.GetString(); - return MIstatus::success; + return MIstatus::success; } - diff --git a/tools/lldb-mi/MICmnMIOutOfBandRecord.h b/tools/lldb-mi/MICmnMIOutOfBandRecord.h index 1a8f7a2e2009..179e37523524 100644 --- a/tools/lldb-mi/MICmnMIOutOfBandRecord.h +++ b/tools/lldb-mi/MICmnMIOutOfBandRecord.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnMIOutOfBandRecord.h +// File: MICmnMIOutOfBandRecord.h // -// Overview: CMICmnMIOutOfBandRecord interface. +// Overview: CMICmnMIOutOfBandRecord interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -30,81 +30,81 @@ #include "MICmnMIValueResult.h" //++ ============================================================================ -// Details: MI common code MI Out-of-band (Async) Record class. A class that encapsulates -// MI result record data and the forming/format of data added to it. -// Out-of-band records are used to notify the GDB/MI client of additional -// changes that have occurred. Those changes can either be a consequence -// of GDB/MI (e.g., a breakpoint modified) or a result of target activity -// (e.g., target stopped). -// The syntax is as follows: -// "*" type ( "," result )* -// type ==> running | stopped +// Details: MI common code MI Out-of-band (Async) Record class. A class that encapsulates +// MI result record data and the forming/format of data added to it. +// Out-of-band records are used to notify the GDB/MI client of additional +// changes that have occurred. Those changes can either be a consequence +// of GDB/MI (e.g., a breakpoint modified) or a result of target activity +// (e.g., target stopped). +// The syntax is as follows: +// "*" type ( "," result )* +// type ==> running | stopped // -// The Out-of-band record can be retrieve at any time *this object is -// instantiated so unless work is done on *this Out-of-band record then it is -// possible to return a malformed Out-of-band record. If nothing has been set -// or added to *this MI Out-of-band record object then text "" will -// be returned. +// The Out-of-band record can be retrieve at any time *this object is +// instantiated so unless work is done on *this Out-of-band record then it is +// possible to return a malformed Out-of-band record. If nothing has been set +// or added to *this MI Out-of-band record object then text "" will +// be returned. // -// More information see: -// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html// -// Gotchas: None. -// Authors: Illya Rudkin 24/02/2014. -// Changes: None. +// More information see: +// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html// +// Gotchas: None. +// Authors: Illya Rudkin 24/02/2014. +// Changes: None. //-- class CMICmnMIOutOfBandRecord : public CMICmnBase { -// Enumerations: -public: - //++ - // Details: Enumeration of the type of Out-of-band for *this Out-of-band record - //-- - enum OutOfBand_e - { - eOutOfBand_Running = 0, - eOutOfBand_Stopped, - eOutOfBand_BreakPointCreated, - eOutOfBand_BreakPointModified, - eOutOfBand_Thread, - eOutOfBand_ThreadGroupAdded, - eOutOfBand_ThreadGroupExited, - eOutOfBand_ThreadGroupRemoved, - eOutOfBand_ThreadGroupStarted, - eOutOfBand_ThreadCreated, - eOutOfBand_ThreadExited, - eOutOfBand_ThreadSelected, - eOutOfBand_count // Always the last one - }; + // Enumerations: + public: + //++ + // Details: Enumeration of the type of Out-of-band for *this Out-of-band record + //-- + enum OutOfBand_e + { + eOutOfBand_Running = 0, + eOutOfBand_Stopped, + eOutOfBand_BreakPointCreated, + eOutOfBand_BreakPointModified, + eOutOfBand_Thread, + eOutOfBand_ThreadGroupAdded, + eOutOfBand_ThreadGroupExited, + eOutOfBand_ThreadGroupRemoved, + eOutOfBand_ThreadGroupStarted, + eOutOfBand_ThreadCreated, + eOutOfBand_ThreadExited, + eOutOfBand_ThreadSelected, + eOutOfBand_count // Always the last one + }; -// Typedefs: -public: - typedef std::map< OutOfBand_e, CMIUtilString > MapOutOfBandToOutOfBandText_t; - typedef std::map< OutOfBand_e, CMIUtilString > MapOutOfBandToToken_t; + // Typedefs: + public: + typedef std::map MapOutOfBandToOutOfBandText_t; + typedef std::map MapOutOfBandToToken_t; -// Methods: -public: - /* ctor */ CMICmnMIOutOfBandRecord( void ); - /* ctor */ CMICmnMIOutOfBandRecord( const OutOfBand_e veType ); - /* ctor */ CMICmnMIOutOfBandRecord( const OutOfBand_e veType, const CMICmnMIValueResult & vValue ); - // - const CMIUtilString & GetString( void ) const; - bool Add( const CMICmnMIValue & vMIValue ); + // Methods: + public: + /* ctor */ CMICmnMIOutOfBandRecord(void); + /* ctor */ CMICmnMIOutOfBandRecord(const OutOfBand_e veType); + /* ctor */ CMICmnMIOutOfBandRecord(const OutOfBand_e veType, const CMICmnMIValueResult &vValue); + // + const CMIUtilString &GetString(void) const; + bool Add(const CMICmnMIValue &vMIValue); -// Overridden: -public: - // From CMICmnBase - /* dtor */ virtual ~CMICmnMIOutOfBandRecord( void ); + // Overridden: + public: + // From CMICmnBase + /* dtor */ virtual ~CMICmnMIOutOfBandRecord(void); -// Methods: -private: - bool BuildAsyncRecord( void ); + // Methods: + private: + bool BuildAsyncRecord(void); -// Attributes: -private: - static MapOutOfBandToOutOfBandText_t ms_constMapOutOfBandToAsyncRecordText; - static MapOutOfBandToToken_t ms_constMapOutOfBandTextToToken; - // - OutOfBand_e m_eResultAsyncRecordClass; - CMIUtilString m_strAsyncRecord; // Holds the text version of the result record to date - CMICmnMIValueResult m_partResult; + // Attributes: + private: + static MapOutOfBandToOutOfBandText_t ms_constMapOutOfBandToAsyncRecordText; + static MapOutOfBandToToken_t ms_constMapOutOfBandTextToToken; + // + OutOfBand_e m_eResultAsyncRecordClass; + CMIUtilString m_strAsyncRecord; // Holds the text version of the result record to date + CMICmnMIValueResult m_partResult; }; diff --git a/tools/lldb-mi/MICmnMIResultRecord.cpp b/tools/lldb-mi/MICmnMIResultRecord.cpp index 195167981d8c..21cf326aca5e 100644 --- a/tools/lldb-mi/MICmnMIResultRecord.cpp +++ b/tools/lldb-mi/MICmnMIResultRecord.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnMIResultRecord.h +// File: MICmnMIResultRecord.h // -// Overview: CMICmnMIResultRecord implementation. +// Overview: CMICmnMIResultRecord implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -24,119 +24,121 @@ #include "MICmnResources.h" // Instantiations: -CMICmnMIResultRecord::MapResultClassToResultClassText_t ms_MapResultClassToResultClassText = -{ - { CMICmnMIResultRecord::eResultClass_Done, "done" }, - { CMICmnMIResultRecord::eResultClass_Running, "running" }, - { CMICmnMIResultRecord::eResultClass_Connected, "connected" }, - { CMICmnMIResultRecord::eResultClass_Error, "error" }, - { CMICmnMIResultRecord::eResultClass_Exit, "exit" } -}; -const CMIUtilString CMICmnMIResultRecord::ms_constStrResultRecordHat( "^"); +CMICmnMIResultRecord::MapResultClassToResultClassText_t ms_MapResultClassToResultClassText = { + {CMICmnMIResultRecord::eResultClass_Done, "done"}, + {CMICmnMIResultRecord::eResultClass_Running, "running"}, + {CMICmnMIResultRecord::eResultClass_Connected, "connected"}, + {CMICmnMIResultRecord::eResultClass_Error, "error"}, + {CMICmnMIResultRecord::eResultClass_Exit, "exit"}}; +const CMIUtilString CMICmnMIResultRecord::ms_constStrResultRecordHat("^"); //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIResultRecord constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnMIResultRecord constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnMIResultRecord::CMICmnMIResultRecord( void ) -: m_strResultRecord( MIRSRC( IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION ) ) +CMICmnMIResultRecord::CMICmnMIResultRecord(void) + : m_strResultRecord(MIRSRC(IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION)) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIResultRecord constructor. -// Type: Method. -// Args: vrToken - (R) The command's transaction ID or token. -// veType - (R) A MI result class enumeration. -// Return: None. -// Throws: None. +// Details: CMICmnMIResultRecord constructor. +// Type: Method. +// Args: vrToken - (R) The command's transaction ID or token. +// veType - (R) A MI result class enumeration. +// Return: None. +// Throws: None. //-- -CMICmnMIResultRecord::CMICmnMIResultRecord( const CMIUtilString & vrToken, const ResultClass_e veType ) -: m_strResultRecordToken( vrToken ) -, m_eResultRecordResultClass( veType ) -, m_strResultRecord( MIRSRC( IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION ) ) +CMICmnMIResultRecord::CMICmnMIResultRecord(const CMIUtilString &vrToken, const ResultClass_e veType) + : m_strResultRecordToken(vrToken) + , m_eResultRecordResultClass(veType) + , m_strResultRecord(MIRSRC(IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION)) { - BuildResultRecord(); + BuildResultRecord(); } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIResultRecord constructor. -// Type: Method. -// Args: vrToken - (R) The command's transaction ID or token. -// veType - (R) A MI result class enumeration. -// vMIResult - (R) A MI result object. -// Return: None. -// Throws: None. +// Details: CMICmnMIResultRecord constructor. +// Type: Method. +// Args: vrToken - (R) The command's transaction ID or token. +// veType - (R) A MI result class enumeration. +// vMIResult - (R) A MI result object. +// Return: None. +// Throws: None. //-- -CMICmnMIResultRecord::CMICmnMIResultRecord( const CMIUtilString & vrToken, const ResultClass_e veType, const CMICmnMIValueResult & vValue ) -: m_strResultRecordToken( vrToken ) -, m_eResultRecordResultClass( veType ) -, m_strResultRecord( MIRSRC( IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION ) ) -, m_partResult( vValue ) +CMICmnMIResultRecord::CMICmnMIResultRecord(const CMIUtilString &vrToken, const ResultClass_e veType, const CMICmnMIValueResult &vValue) + : m_strResultRecordToken(vrToken) + , m_eResultRecordResultClass(veType) + , m_strResultRecord(MIRSRC(IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION)) + , m_partResult(vValue) { - BuildResultRecord(); - Add( m_partResult ); + BuildResultRecord(); + Add(m_partResult); } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIResultRecord destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnMIResultRecord destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnMIResultRecord::~CMICmnMIResultRecord( void ) +CMICmnMIResultRecord::~CMICmnMIResultRecord(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Return the MI result record as a string. The string is a direct result of -// work done on *this result record so if not enough data is added then it is -// possible to return a malformed result record. If nothing has been set or -// added to *this MI result record object then text "" will be returned. -// Type: Method. -// Args: None. -// Return: CMIUtilString & - MI output text. -// Throws: None. +// Details: Return the MI result record as a string. The string is a direct result of +// work done on *this result record so if not enough data is added then it is +// possible to return a malformed result record. If nothing has been set or +// added to *this MI result record object then text "" will be returned. +// Type: Method. +// Args: None. +// Return: CMIUtilString & - MI output text. +// Throws: None. //-- -const CMIUtilString & CMICmnMIResultRecord::GetString( void ) const +const CMIUtilString & +CMICmnMIResultRecord::GetString(void) const { - return m_strResultRecord; + return m_strResultRecord; } - + //++ ------------------------------------------------------------------------------------ -// Details: Build the result record's mandatory data part. The part up to the first -// (additional) result i.e. result-record ==> [ token ] "^" result-class. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Build the result record's mandatory data part. The part up to the first +// (additional) result i.e. result-record ==> [ token ] "^" result-class. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIResultRecord::BuildResultRecord( void ) +bool +CMICmnMIResultRecord::BuildResultRecord(void) { - const MIchar * pFormat = "%s%s%s"; - const CMIUtilString & rStrResultRecord( ms_MapResultClassToResultClassText[ m_eResultRecordResultClass ] ); - m_strResultRecord = CMIUtilString::Format( pFormat, m_strResultRecordToken.c_str(), ms_constStrResultRecordHat.c_str(), rStrResultRecord.c_str() ); + const MIchar *pFormat = "%s%s%s"; + const CMIUtilString &rStrResultRecord(ms_MapResultClassToResultClassText[m_eResultRecordResultClass]); + m_strResultRecord = + CMIUtilString::Format(pFormat, m_strResultRecordToken.c_str(), ms_constStrResultRecordHat.c_str(), rStrResultRecord.c_str()); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Add to *this result record additional information. -// Type: Method. -// Args: vMIValue - (R) A MI value derived object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Add to *this result record additional information. +// Type: Method. +// Args: vMIValue - (R) A MI value derived object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIResultRecord::Add( const CMICmnMIValue & vMIValue ) +bool +CMICmnMIResultRecord::Add(const CMICmnMIValue &vMIValue) { - m_strResultRecord += ","; - m_strResultRecord += vMIValue.GetString(); + m_strResultRecord += ","; + m_strResultRecord += vMIValue.GetString(); - return MIstatus::success; + return MIstatus::success; } diff --git a/tools/lldb-mi/MICmnMIResultRecord.h b/tools/lldb-mi/MICmnMIResultRecord.h index c76587d606c8..9d1f188c1eef 100644 --- a/tools/lldb-mi/MICmnMIResultRecord.h +++ b/tools/lldb-mi/MICmnMIResultRecord.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnMIResultRecord.h +// File: MICmnMIResultRecord.h // -// Overview: CMICmnMIResultRecord interface. +// Overview: CMICmnMIResultRecord interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -30,77 +30,77 @@ #include "MICmnMIValueResult.h" //++ ============================================================================ -// Details: MI common code MI Result Record class. A class that encapsulates -// MI result record data and the forming/format of data added to it. -// The syntax is as follows: -// result-record ==> [ token ] "^" result-class ( "," result )* nl -// token = any sequence of digits -// * = 0 to many -// nl = CR | CR_LF -// result-class ==> "done" | "running" | "connected" | "error" | "exit" -// result ==> variable "=" value -// value ==> const | tuple | list -// const ==> c-string (7 bit iso c string content) i.e. "all" inc quotes -// tuple ==> "{}" | "{" result ( "," result )* "}" -// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" +// Details: MI common code MI Result Record class. A class that encapsulates +// MI result record data and the forming/format of data added to it. +// The syntax is as follows: +// result-record ==> [ token ] "^" result-class ( "," result )* nl +// token = any sequence of digits +// * = 0 to many +// nl = CR | CR_LF +// result-class ==> "done" | "running" | "connected" | "error" | "exit" +// result ==> variable "=" value +// value ==> const | tuple | list +// const ==> c-string (7 bit iso c string content) i.e. "all" inc quotes +// tuple ==> "{}" | "{" result ( "," result )* "}" +// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" // -// The result record can be retrieve at any time *this object is -// instantiated so unless work is done on *this result record then it is -// possible to return a malformed result record. If nothing has been set -// or added to *this MI result record object then text "" will -// be returned. -// More information see: -// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html -// Gotchas: None. -// Authors: Illya Rudkin 24/02/2014. -// Changes: None. +// The result record can be retrieve at any time *this object is +// instantiated so unless work is done on *this result record then it is +// possible to return a malformed result record. If nothing has been set +// or added to *this MI result record object then text "" will +// be returned. +// More information see: +// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html +// Gotchas: None. +// Authors: Illya Rudkin 24/02/2014. +// Changes: None. //-- class CMICmnMIResultRecord : public CMICmnBase { -// Enumerations: -public: - //++ - // Details: Enumeration of the result class for *this result record - //-- - enum ResultClass_e - { - eResultClass_Done = 0, - eResultClass_Running, - eResultClass_Connected, - eResultClass_Error, - eResultClass_Exit, - eResultClass_count // Always the last one - }; + // Enumerations: + public: + //++ + // Details: Enumeration of the result class for *this result record + //-- + enum ResultClass_e + { + eResultClass_Done = 0, + eResultClass_Running, + eResultClass_Connected, + eResultClass_Error, + eResultClass_Exit, + eResultClass_count // Always the last one + }; -// Typedefs: -public: - typedef std::map< ResultClass_e, CMIUtilString > MapResultClassToResultClassText_t; + // Typedefs: + public: + typedef std::map MapResultClassToResultClassText_t; -// Methods: -public: - /* ctor */ CMICmnMIResultRecord( void ); - /* ctor */ CMICmnMIResultRecord( const CMIUtilString & vrToken, const ResultClass_e veType ); - /* ctor */ CMICmnMIResultRecord( const CMIUtilString & vrToken, const ResultClass_e veType, const CMICmnMIValueResult & vValue ); - // - const CMIUtilString & GetString( void ) const; - bool Add( const CMICmnMIValue & vMIValue ); + // Methods: + public: + /* ctor */ CMICmnMIResultRecord(void); + /* ctor */ CMICmnMIResultRecord(const CMIUtilString &vrToken, const ResultClass_e veType); + /* ctor */ CMICmnMIResultRecord(const CMIUtilString &vrToken, const ResultClass_e veType, const CMICmnMIValueResult &vValue); + // + const CMIUtilString &GetString(void) const; + bool Add(const CMICmnMIValue &vMIValue); -// Overridden: -public: - // From CMICmnBase - /* dtor */ virtual ~CMICmnMIResultRecord( void ); + // Overridden: + public: + // From CMICmnBase + /* dtor */ virtual ~CMICmnMIResultRecord(void); -// Methods: -private: - bool BuildResultRecord( void ); + // Methods: + private: + bool BuildResultRecord(void); -// Attributes: -private: - static const CMIUtilString ms_constStrResultRecordHat; - static MapResultClassToResultClassText_t ms_constMapResultClassToResultClassText; - // - CMIUtilString m_strResultRecordToken; - ResultClass_e m_eResultRecordResultClass; - CMIUtilString m_strResultRecord; // Holds the text version of the result record to date - CMICmnMIValueResult m_partResult; + // Attributes: + private: + static const CMIUtilString ms_constStrResultRecordHat; + static MapResultClassToResultClassText_t ms_constMapResultClassToResultClassText; + // + CMIUtilString m_strResultRecordToken; + ResultClass_e m_eResultRecordResultClass; + CMIUtilString m_strResultRecord; // Holds the text version of the result record to date + CMICmnMIValueResult m_partResult; }; diff --git a/tools/lldb-mi/MICmnMIValue.cpp b/tools/lldb-mi/MICmnMIValue.cpp index f9fb08bf642d..8c0440115bf3 100644 --- a/tools/lldb-mi/MICmnMIValue.cpp +++ b/tools/lldb-mi/MICmnMIValue.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnMIValue.h +// File: MICmnMIValue.h // -// Overview: CMICmnMIValue implementation. +// Overview: CMICmnMIValue implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -24,41 +24,41 @@ #include "MICmnResources.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValue constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnMIValue constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnMIValue::CMICmnMIValue( void ) -: m_strValue( MIRSRC( IDS_WORD_INVALIDBRKTS ) ) -, m_bJustConstructed( true ) +CMICmnMIValue::CMICmnMIValue(void) + : m_strValue(MIRSRC(IDS_WORD_INVALIDBRKTS)) + , m_bJustConstructed(true) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValue destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnMIValue destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnMIValue::~CMICmnMIValue( void ) +CMICmnMIValue::~CMICmnMIValue(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Return the MI value as a string. The string is a direct result of -// work done on *this value so if not enough data is added then it is -// possible to return a malformed value. If nothing has been set or -// added to *this MI value object then text "" will be returned. -// Type: Method. -// Args: None. -// Return: CMIUtilString & - MI output text. -// Throws: None. +// Details: Return the MI value as a string. The string is a direct result of +// work done on *this value so if not enough data is added then it is +// possible to return a malformed value. If nothing has been set or +// added to *this MI value object then text "" will be returned. +// Type: Method. +// Args: None. +// Return: CMIUtilString & - MI output text. +// Throws: None. //-- -const CMIUtilString & CMICmnMIValue::GetString( void ) const +const CMIUtilString & +CMICmnMIValue::GetString(void) const { - return m_strValue; + return m_strValue; } - diff --git a/tools/lldb-mi/MICmnMIValue.h b/tools/lldb-mi/MICmnMIValue.h index 4cf03122cc28..2b60168db524 100644 --- a/tools/lldb-mi/MICmnMIValue.h +++ b/tools/lldb-mi/MICmnMIValue.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnMIValue.h +// File: MICmnMIValue.h // -// Overview: CMICmnMIValue interface. +// Overview: CMICmnMIValue interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -25,40 +25,40 @@ #include "MICmnBase.h" //++ ============================================================================ -// Details: MI common code MI Result class. Part of the CMICmnMIValueRecord -// set of objects. -// The syntax is as follows: -// result-record ==> [ token ] "^" result-class ( "," result )* nl -// token = any sequence of digits -// * = 0 to many -// nl = CR | CR_LF -// result-class ==> "done" | "running" | "connected" | "error" | "exit" -// result ==> variable "=" value -// value ==> const | tuple | list -// const ==> c-string (7 bit iso c string content) -// tuple ==> "{}" | "{" result ( "," result )* "}" -// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" -// More information see: -// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html -// Gotchas: None. -// Authors: Illya Rudkin 24/02/2014. -// Changes: None. +// Details: MI common code MI Result class. Part of the CMICmnMIValueRecord +// set of objects. +// The syntax is as follows: +// result-record ==> [ token ] "^" result-class ( "," result )* nl +// token = any sequence of digits +// * = 0 to many +// nl = CR | CR_LF +// result-class ==> "done" | "running" | "connected" | "error" | "exit" +// result ==> variable "=" value +// value ==> const | tuple | list +// const ==> c-string (7 bit iso c string content) +// tuple ==> "{}" | "{" result ( "," result )* "}" +// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" +// More information see: +// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html +// Gotchas: None. +// Authors: Illya Rudkin 24/02/2014. +// Changes: None. //-- class CMICmnMIValue : public CMICmnBase { -// Methods: -public: - /* ctor */ CMICmnMIValue( void ); - // - const CMIUtilString & GetString( void ) const; + // Methods: + public: + /* ctor */ CMICmnMIValue(void); + // + const CMIUtilString &GetString(void) const; -// Overridden: -public: - // From CMICmnBase - /* dtor */ virtual ~CMICmnMIValue( void ); + // Overridden: + public: + // From CMICmnBase + /* dtor */ virtual ~CMICmnMIValue(void); -// Attributes: -protected: - CMIUtilString m_strValue; - bool m_bJustConstructed; // True = *this just constructed with no value, false = *this has had value added to it + // Attributes: + protected: + CMIUtilString m_strValue; + bool m_bJustConstructed; // True = *this just constructed with no value, false = *this has had value added to it }; diff --git a/tools/lldb-mi/MICmnMIValueConst.cpp b/tools/lldb-mi/MICmnMIValueConst.cpp index afac8df07d78..7aa0f7903558 100644 --- a/tools/lldb-mi/MICmnMIValueConst.cpp +++ b/tools/lldb-mi/MICmnMIValueConst.cpp @@ -8,91 +8,92 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnMIValueConst.h +// File: MICmnMIValueConst.h // -// Overview: CMICmnMIValueConst implementation. +// Overview: CMICmnMIValueConst implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: #include "MICmnMIValueConst.h" // Instantiations: -const CMIUtilString CMICmnMIValueConst::ms_constStrDblQuote( "\"" ); +const CMIUtilString CMICmnMIValueConst::ms_constStrDblQuote("\""); //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValueConst constructor. -// Type: Method. -// Args: vString - (R) MI Const c-string value. -// Return: None. -// Throws: None. +// Details: CMICmnMIValueConst constructor. +// Type: Method. +// Args: vString - (R) MI Const c-string value. +// Return: None. +// Throws: None. //-- -CMICmnMIValueConst::CMICmnMIValueConst( const CMIUtilString & vString ) -: m_strPartConst( vString ) -, m_bNoQuotes( false ) +CMICmnMIValueConst::CMICmnMIValueConst(const CMIUtilString &vString) + : m_strPartConst(vString) + , m_bNoQuotes(false) { - BuildConst(); + BuildConst(); } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValueConst constructor. -// Type: Method. -// Args: vString - (R) MI Const c-string value. -// vbNoQuotes - (R) True = return string not surrounded with quotes, false = use quotes. -// Return: None. -// Throws: None. +// Details: CMICmnMIValueConst constructor. +// Type: Method. +// Args: vString - (R) MI Const c-string value. +// vbNoQuotes - (R) True = return string not surrounded with quotes, false = use quotes. +// Return: None. +// Throws: None. //-- -CMICmnMIValueConst::CMICmnMIValueConst( const CMIUtilString & vString, const bool vbNoQuotes ) -: m_strPartConst( vString ) -, m_bNoQuotes( vbNoQuotes ) +CMICmnMIValueConst::CMICmnMIValueConst(const CMIUtilString &vString, const bool vbNoQuotes) + : m_strPartConst(vString) + , m_bNoQuotes(vbNoQuotes) { - BuildConst(); + BuildConst(); } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValueConst destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnMIValueConst destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnMIValueConst::~CMICmnMIValueConst( void ) +CMICmnMIValueConst::~CMICmnMIValueConst(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Build the Value Const data. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Build the Value Const data. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIValueConst::BuildConst( void ) +bool +CMICmnMIValueConst::BuildConst(void) { - if( m_strPartConst.length() != 0 ) - { - const CMIUtilString strValue( m_strPartConst.StripCREndOfLine() ); - if( m_bNoQuotes ) - { - m_strValue = strValue; - } - else - { - const MIchar * pFormat = "%s%s%s"; - m_strValue = CMIUtilString::Format( pFormat, ms_constStrDblQuote.c_str(), strValue.c_str(), ms_constStrDblQuote.c_str() ); - } - } - else - { - const MIchar * pFormat = "%s%s"; - m_strValue = CMIUtilString::Format( pFormat, ms_constStrDblQuote.c_str(), ms_constStrDblQuote.c_str() ); - } + if (m_strPartConst.length() != 0) + { + const CMIUtilString strValue(m_strPartConst.StripCREndOfLine()); + if (m_bNoQuotes) + { + m_strValue = strValue; + } + else + { + const MIchar *pFormat = "%s%s%s"; + m_strValue = CMIUtilString::Format(pFormat, ms_constStrDblQuote.c_str(), strValue.c_str(), ms_constStrDblQuote.c_str()); + } + } + else + { + const MIchar *pFormat = "%s%s"; + m_strValue = CMIUtilString::Format(pFormat, ms_constStrDblQuote.c_str(), ms_constStrDblQuote.c_str()); + } - return MIstatus::success; -} \ No newline at end of file + return MIstatus::success; +} diff --git a/tools/lldb-mi/MICmnMIValueConst.h b/tools/lldb-mi/MICmnMIValueConst.h index ddb440d7c6ec..72be01fa3db1 100644 --- a/tools/lldb-mi/MICmnMIValueConst.h +++ b/tools/lldb-mi/MICmnMIValueConst.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnMIValueConst.h +// File: MICmnMIValueConst.h // -// Overview: CMICmnMIValueConst interface. +// Overview: CMICmnMIValueConst interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -25,48 +25,48 @@ #include "MICmnMIValue.h" //++ ============================================================================ -// Details: MI common code MI Result class. Part of the CMICmnMIValueConstRecord -// set of objects. -// The syntax is as follows: -// result-record ==> [ token ] "^" result-class ( "," result )* nl -// token = any sequence of digits -// * = 0 to many -// nl = CR | CR_LF -// result-class ==> "done" | "running" | "connected" | "error" | "exit" -// result ==> variable "=" value -// value ==> const | tuple | list -// const ==> c-string (7 bit iso c string content) -// tuple ==> "{}" | "{" result ( "," result )* "}" -// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" -// More information see: -// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html +// Details: MI common code MI Result class. Part of the CMICmnMIValueConstRecord +// set of objects. +// The syntax is as follows: +// result-record ==> [ token ] "^" result-class ( "," result )* nl +// token = any sequence of digits +// * = 0 to many +// nl = CR | CR_LF +// result-class ==> "done" | "running" | "connected" | "error" | "exit" +// result ==> variable "=" value +// value ==> const | tuple | list +// const ==> c-string (7 bit iso c string content) +// tuple ==> "{}" | "{" result ( "," result )* "}" +// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" +// More information see: +// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html // -// The text formed in *this Result class is stripped of any '\n' characters. +// The text formed in *this Result class is stripped of any '\n' characters. // -// Gotchas: None. -// Authors: Illya Rudkin 24/02/2014. -// Changes: None. +// Gotchas: None. +// Authors: Illya Rudkin 24/02/2014. +// Changes: None. //-- -class CMICmnMIValueConst : public CMICmnMIValue +class CMICmnMIValueConst : public CMICmnMIValue { -// Methods: -public: - /* ctor */ CMICmnMIValueConst( const CMIUtilString & vString ); - /* ctor */ CMICmnMIValueConst( const CMIUtilString & vString, const bool vbNoQuotes ); + // Methods: + public: + /* ctor */ CMICmnMIValueConst(const CMIUtilString &vString); + /* ctor */ CMICmnMIValueConst(const CMIUtilString &vString, const bool vbNoQuotes); -// Overridden: -public: - // From CMICmnBase - /* dtor */ virtual ~CMICmnMIValueConst( void ); + // Overridden: + public: + // From CMICmnBase + /* dtor */ virtual ~CMICmnMIValueConst(void); -// Methods: -private: - bool BuildConst( void ); - -// Attributes: -private: - static const CMIUtilString ms_constStrDblQuote; - // - CMIUtilString m_strPartConst; - bool m_bNoQuotes; // True = return string not surrounded with quotes, false = use quotes + // Methods: + private: + bool BuildConst(void); + + // Attributes: + private: + static const CMIUtilString ms_constStrDblQuote; + // + CMIUtilString m_strPartConst; + bool m_bNoQuotes; // True = return string not surrounded with quotes, false = use quotes }; diff --git a/tools/lldb-mi/MICmnMIValueList.cpp b/tools/lldb-mi/MICmnMIValueList.cpp index 97a08cd29f09..2e6078cbea1f 100644 --- a/tools/lldb-mi/MICmnMIValueList.cpp +++ b/tools/lldb-mi/MICmnMIValueList.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnMIValueList.h +// File: MICmnMIValueList.h // -// Overview: CMICmnMIValueList implementation. +// Overview: CMICmnMIValueList implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -24,180 +24,186 @@ #include "MICmnResources.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValueList constructor. -// Type: Method. -// Args: vbValueTypeList - (R) True = yes value type list, false = result type list. -// Return: None. -// Throws: None. +// Details: CMICmnMIValueList constructor. +// Type: Method. +// Args: vbValueTypeList - (R) True = yes value type list, false = result type list. +// Return: None. +// Throws: None. //-- -CMICmnMIValueList::CMICmnMIValueList( const bool vbValueTypeList ) +CMICmnMIValueList::CMICmnMIValueList(const bool vbValueTypeList) { - m_strValue = "[]"; + m_strValue = "[]"; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValueList constructor. -// Construct a results only list. -// return MIstatus::failure. -// Type: Method. -// Args: vResult - (R) MI result object. -// Return: None. -// Throws: None. +// Details: CMICmnMIValueList constructor. +// Construct a results only list. +// return MIstatus::failure. +// Type: Method. +// Args: vResult - (R) MI result object. +// Return: None. +// Throws: None. //-- -CMICmnMIValueList::CMICmnMIValueList( const CMICmnMIValueResult & vResult ) +CMICmnMIValueList::CMICmnMIValueList(const CMICmnMIValueResult &vResult) { - m_strValue = vResult.GetString(); - BuildList(); - m_bJustConstructed = false; + m_strValue = vResult.GetString(); + BuildList(); + m_bJustConstructed = false; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValueList constructor. -// Construct a value only list. -// Type: Method. -// Args: vValue - (R) MI value object. -// Return: None. -// Throws: None. +// Details: CMICmnMIValueList constructor. +// Construct a value only list. +// Type: Method. +// Args: vValue - (R) MI value object. +// Return: None. +// Throws: None. //-- -CMICmnMIValueList::CMICmnMIValueList( const CMICmnMIValue & vValue ) +CMICmnMIValueList::CMICmnMIValueList(const CMICmnMIValue &vValue) { - m_strValue = vValue.GetString(); - BuildList(); - m_bJustConstructed = false; + m_strValue = vValue.GetString(); + BuildList(); + m_bJustConstructed = false; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValueList destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnMIValueList destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnMIValueList::~CMICmnMIValueList( void ) +CMICmnMIValueList::~CMICmnMIValueList(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Build the result value's mandatory data part, one tuple -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Build the result value's mandatory data part, one tuple +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIValueList::BuildList( void ) +bool +CMICmnMIValueList::BuildList(void) { - const MIchar * pFormat = "[%s]"; - m_strValue = CMIUtilString::Format( pFormat, m_strValue.c_str() ); - - return MIstatus::success; + const MIchar *pFormat = "[%s]"; + m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str()); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Add another MI result object to the value list's of list is results. -// Only result obejcts can be added to a list of result otherwise this function -// will return MIstatus::failure. -// Type: Method. -// Args: vResult - (R) The MI result object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Add another MI result object to the value list's of list is results. +// Only result obejcts can be added to a list of result otherwise this function +// will return MIstatus::failure. +// Type: Method. +// Args: vResult - (R) The MI result object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIValueList::Add( const CMICmnMIValueResult & vResult ) +bool +CMICmnMIValueList::Add(const CMICmnMIValueResult &vResult) { - return BuildList( vResult ); + return BuildList(vResult); } //++ ------------------------------------------------------------------------------------ -// Details: Add another MI value object to the value list's of list is values. -// Only values objects can be added to a list of values otherwise this function -// will return MIstatus::failure. -// Type: Method. -// Args: vValue - (R) The MI value object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Add another MI value object to the value list's of list is values. +// Only values objects can be added to a list of values otherwise this function +// will return MIstatus::failure. +// Type: Method. +// Args: vValue - (R) The MI value object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIValueList::Add( const CMICmnMIValue & vValue ) +bool +CMICmnMIValueList::Add(const CMICmnMIValue &vValue) { - return BuildList( vValue ); + return BuildList(vValue); } //++ ------------------------------------------------------------------------------------ -// Details: Add another MI result object to the value list's of list is results. -// Only result obejcts can be added to a list of result otherwise this function -// will return MIstatus::failure. -// Type: Method. -// Args: vResult - (R) The MI result object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Add another MI result object to the value list's of list is results. +// Only result obejcts can be added to a list of result otherwise this function +// will return MIstatus::failure. +// Type: Method. +// Args: vResult - (R) The MI result object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIValueList::BuildList( const CMICmnMIValueResult & vResult ) +bool +CMICmnMIValueList::BuildList(const CMICmnMIValueResult &vResult) { - // Clear out the default "" text - if( m_bJustConstructed ) - { - m_bJustConstructed = false; - m_strValue = vResult.GetString(); - return BuildList(); - } - - const CMIUtilString data( ExtractContentNoBrackets() ); - const MIchar * pFormat = "[%s,%s]"; - m_strValue = CMIUtilString::Format( pFormat, data.c_str(), vResult.GetString().c_str() ); - - return MIstatus::success; + // Clear out the default "" text + if (m_bJustConstructed) + { + m_bJustConstructed = false; + m_strValue = vResult.GetString(); + return BuildList(); + } + + const CMIUtilString data(ExtractContentNoBrackets()); + const MIchar *pFormat = "[%s,%s]"; + m_strValue = CMIUtilString::Format(pFormat, data.c_str(), vResult.GetString().c_str()); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Add another MI value object to the value list's of list is values. -// Only values objects can be added to a list of values otherwise this function -// will return MIstatus::failure. -// Type: Method. -// Args: vValue - (R) The MI value object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Add another MI value object to the value list's of list is values. +// Only values objects can be added to a list of values otherwise this function +// will return MIstatus::failure. +// Type: Method. +// Args: vValue - (R) The MI value object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIValueList::BuildList( const CMICmnMIValue & vValue ) +bool +CMICmnMIValueList::BuildList(const CMICmnMIValue &vValue) { - // Clear out the default "" text - if( m_bJustConstructed ) - { - m_bJustConstructed = false; - m_strValue = vValue.GetString(); - return BuildList(); - } - - const MIchar * pFormat = "[%s,%s]"; - m_strValue = m_strValue.FindAndReplace( "[", "" ); - m_strValue = m_strValue.FindAndReplace( "]", "" ); - m_strValue = CMIUtilString::Format( pFormat, m_strValue.c_str(), vValue.GetString().c_str() ); - - return MIstatus::success; + // Clear out the default "" text + if (m_bJustConstructed) + { + m_bJustConstructed = false; + m_strValue = vValue.GetString(); + return BuildList(); + } + + const MIchar *pFormat = "[%s,%s]"; + m_strValue = m_strValue.FindAndReplace("[", ""); + m_strValue = m_strValue.FindAndReplace("]", ""); + m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str(), vValue.GetString().c_str()); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the contents of *this value object but without the outer most -// brackets. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Data within the object. -// Throws: None. +// Details: Retrieve the contents of *this value object but without the outer most +// brackets. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Data within the object. +// Throws: None. //-- -CMIUtilString CMICmnMIValueList::ExtractContentNoBrackets( void ) const +CMIUtilString +CMICmnMIValueList::ExtractContentNoBrackets(void) const { - CMIUtilString data( m_strValue ); - - if( data[ 0 ] == '[' ) - { - data = data.substr( 1, data.length() - 1 ); - } - if( data[ data.size() - 1 ] == ']' ) - { - data = data.substr( 0, data.length() - 1 ); - } - - return data; + CMIUtilString data(m_strValue); + + if (data[0] == '[') + { + data = data.substr(1, data.length() - 1); + } + if (data[data.size() - 1] == ']') + { + data = data.substr(0, data.length() - 1); + } + + return data; } diff --git a/tools/lldb-mi/MICmnMIValueList.h b/tools/lldb-mi/MICmnMIValueList.h index cd1a98f7705f..e7811e7d7bab 100644 --- a/tools/lldb-mi/MICmnMIValueList.h +++ b/tools/lldb-mi/MICmnMIValueList.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnMIValueList.h +// File: MICmnMIValueList.h // -// Overview: CMICmnMIValueList interface. +// Overview: CMICmnMIValueList interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -26,45 +26,45 @@ #include "MICmnMIValueResult.h" //++ ============================================================================ -// Details: MI common code MI Result class. Part of the CMICmnMIValueListRecord -// set of objects. -// The syntax is as follows: -// result-record ==> [ token ] "^" result-class ( "," result )* nl -// token = any sequence of digits -// * = 0 to many -// nl = CR | CR_LF -// result-class ==> "done" | "running" | "connected" | "error" | "exit" -// result ==> variable "=" value -// value ==> const | tuple | list -// const ==> c-string (7 bit iso c string content) -// tuple ==> "{}" | "{" result ( "," result )* "}" -// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" -// More information see: -// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html -// Gotchas: None. -// Authors: Illya Rudkin 24/02/2014. -// Changes: None. +// Details: MI common code MI Result class. Part of the CMICmnMIValueListRecord +// set of objects. +// The syntax is as follows: +// result-record ==> [ token ] "^" result-class ( "," result )* nl +// token = any sequence of digits +// * = 0 to many +// nl = CR | CR_LF +// result-class ==> "done" | "running" | "connected" | "error" | "exit" +// result ==> variable "=" value +// value ==> const | tuple | list +// const ==> c-string (7 bit iso c string content) +// tuple ==> "{}" | "{" result ( "," result )* "}" +// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" +// More information see: +// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html +// Gotchas: None. +// Authors: Illya Rudkin 24/02/2014. +// Changes: None. //-- class CMICmnMIValueList : public CMICmnMIValue { -// Methods: -public: - /* ctor */ CMICmnMIValueList( const bool vbValueTypeList ); - /* ctor */ CMICmnMIValueList( const CMICmnMIValueResult & vResult ); - /* ctor */ CMICmnMIValueList( const CMICmnMIValue & vValue ); - // - bool Add( const CMICmnMIValueResult & vResult ); - bool Add( const CMICmnMIValue & vValue ); - CMIUtilString ExtractContentNoBrackets( void ) const; + // Methods: + public: + /* ctor */ CMICmnMIValueList(const bool vbValueTypeList); + /* ctor */ CMICmnMIValueList(const CMICmnMIValueResult &vResult); + /* ctor */ CMICmnMIValueList(const CMICmnMIValue &vValue); + // + bool Add(const CMICmnMIValueResult &vResult); + bool Add(const CMICmnMIValue &vValue); + CMIUtilString ExtractContentNoBrackets(void) const; -// Overridden: -public: - // From CMICmnBase - /* dtor */ virtual ~CMICmnMIValueList( void ); + // Overridden: + public: + // From CMICmnBase + /* dtor */ virtual ~CMICmnMIValueList(void); -// Methods: -private: - bool BuildList( void ); - bool BuildList( const CMICmnMIValueResult & vResult ); - bool BuildList( const CMICmnMIValue & vResult ); + // Methods: + private: + bool BuildList(void); + bool BuildList(const CMICmnMIValueResult &vResult); + bool BuildList(const CMICmnMIValue &vResult); }; diff --git a/tools/lldb-mi/MICmnMIValueResult.cpp b/tools/lldb-mi/MICmnMIValueResult.cpp index e5cc9ce2bb1c..7735844b14de 100644 --- a/tools/lldb-mi/MICmnMIValueResult.cpp +++ b/tools/lldb-mi/MICmnMIValueResult.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnMIResult.h +// File: MICmnMIResult.h // -// Overview: CMICmnMIValueResult implementation. +// Overview: CMICmnMIValueResult implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -24,118 +24,121 @@ #include "MICmnResources.h" // Instantiations: -const CMIUtilString CMICmnMIValueResult::ms_constStrEqual( "=" ); +const CMIUtilString CMICmnMIValueResult::ms_constStrEqual("="); //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValueResult constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnMIValueResult constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnMIValueResult::CMICmnMIValueResult( void ) -: m_bEmptyConstruction( true ) +CMICmnMIValueResult::CMICmnMIValueResult(void) + : m_bEmptyConstruction(true) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValueResult constructor. -// Type: Method. -// Args: vrVariable - (R) MI value's name. -// vrValue - (R) The MI value. -// Return: None. -// Throws: None. +// Details: CMICmnMIValueResult constructor. +// Type: Method. +// Args: vrVariable - (R) MI value's name. +// vrValue - (R) The MI value. +// Return: None. +// Throws: None. //-- -CMICmnMIValueResult::CMICmnMIValueResult( const CMIUtilString & vrVariable, const CMICmnMIValue & vrValue ) -: m_strPartVariable( vrVariable ) -, m_partMIValue( vrValue ) -, m_bEmptyConstruction( false ) -, m_bUseSpacing( false ) +CMICmnMIValueResult::CMICmnMIValueResult(const CMIUtilString &vrVariable, const CMICmnMIValue &vrValue) + : m_strPartVariable(vrVariable) + , m_partMIValue(vrValue) + , m_bEmptyConstruction(false) + , m_bUseSpacing(false) { - BuildResult(); + BuildResult(); } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValueResult constructor. -// Type: Method. -// Args: vrVariable - (R) MI value's name. -// vrValue - (R) The MI value. -// vbUseSpacing - (R) True = put space seperators into the string, false = no spaces used. -// Return: None. -// Throws: None. +// Details: CMICmnMIValueResult constructor. +// Type: Method. +// Args: vrVariable - (R) MI value's name. +// vrValue - (R) The MI value. +// vbUseSpacing - (R) True = put space seperators into the string, false = no spaces used. +// Return: None. +// Throws: None. //-- -CMICmnMIValueResult::CMICmnMIValueResult( const CMIUtilString & vrVariable, const CMICmnMIValue & vrValue, const bool vbUseSpacing ) -: m_strPartVariable( vrVariable ) -, m_partMIValue( vrValue ) -, m_bEmptyConstruction( false ) -, m_bUseSpacing( vbUseSpacing ) +CMICmnMIValueResult::CMICmnMIValueResult(const CMIUtilString &vrVariable, const CMICmnMIValue &vrValue, const bool vbUseSpacing) + : m_strPartVariable(vrVariable) + , m_partMIValue(vrValue) + , m_bEmptyConstruction(false) + , m_bUseSpacing(vbUseSpacing) { - BuildResult(); + BuildResult(); } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValueResult destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnMIValueResult destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnMIValueResult::~CMICmnMIValueResult( void ) +CMICmnMIValueResult::~CMICmnMIValueResult(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Build the MI value result string. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Build the MI value result string. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIValueResult::BuildResult( void ) +bool +CMICmnMIValueResult::BuildResult(void) { - const MIchar * pFormat = m_bUseSpacing ? "%s %s %s" : "%s%s%s"; - m_strValue = CMIUtilString::Format( pFormat, m_strPartVariable.c_str(), ms_constStrEqual.c_str(), m_partMIValue.GetString().c_str() ); + const MIchar *pFormat = m_bUseSpacing ? "%s %s %s" : "%s%s%s"; + m_strValue = CMIUtilString::Format(pFormat, m_strPartVariable.c_str(), ms_constStrEqual.c_str(), m_partMIValue.GetString().c_str()); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Build the MI value result string. -// Type: Method. -// Args: vrVariable - (R) MI value's name. -// vrValue - (R) The MI value. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Build the MI value result string. +// Type: Method. +// Args: vrVariable - (R) MI value's name. +// vrValue - (R) The MI value. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIValueResult::BuildResult( const CMIUtilString & vVariable, const CMICmnMIValue & vValue ) +bool +CMICmnMIValueResult::BuildResult(const CMIUtilString &vVariable, const CMICmnMIValue &vValue) { - const MIchar * pFormat = m_bUseSpacing ? "%s, %s %s %s" : "%s,%s%s%s"; - m_strValue = CMIUtilString::Format( pFormat, m_strValue.c_str(), vVariable.c_str(), ms_constStrEqual.c_str(), vValue.GetString().c_str() ); + const MIchar *pFormat = m_bUseSpacing ? "%s, %s %s %s" : "%s,%s%s%s"; + m_strValue = + CMIUtilString::Format(pFormat, m_strValue.c_str(), vVariable.c_str(), ms_constStrEqual.c_str(), vValue.GetString().c_str()); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Append another MI value object to *this MI value result. -// Type: Method. -// Args: vrVariable - (R) MI value's name. -// vrValue - (R) The MI value. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Append another MI value object to *this MI value result. +// Type: Method. +// Args: vrVariable - (R) MI value's name. +// vrValue - (R) The MI value. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIValueResult::Add( const CMIUtilString & vrVariable, const CMICmnMIValue & vrValue ) +bool +CMICmnMIValueResult::Add(const CMIUtilString &vrVariable, const CMICmnMIValue &vrValue) { - if( !m_bEmptyConstruction ) - return BuildResult( vrVariable, vrValue ); - else - { - m_bEmptyConstruction = false; - m_strPartVariable = vrVariable; - m_partMIValue = vrValue; - return BuildResult(); - } + if (!m_bEmptyConstruction) + return BuildResult(vrVariable, vrValue); + else + { + m_bEmptyConstruction = false; + m_strPartVariable = vrVariable; + m_partMIValue = vrValue; + return BuildResult(); + } } - diff --git a/tools/lldb-mi/MICmnMIValueResult.h b/tools/lldb-mi/MICmnMIValueResult.h index a9a2a930c93e..ec73e713bc93 100644 --- a/tools/lldb-mi/MICmnMIValueResult.h +++ b/tools/lldb-mi/MICmnMIValueResult.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnMIResult.h +// File: MICmnMIResult.h // -// Overview: CMICmnMIValueResult interface. +// Overview: CMICmnMIValueResult interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -25,51 +25,51 @@ #include "MICmnMIValue.h" //++ ============================================================================ -// Details: MI common code MI Result class. Part of the CMICmnMIValueResultRecord -// set of objects. -// The syntax is as follows: -// result-record ==> [ token ] "^" result-class ( "," result )* nl -// token = any sequence of digits -// * = 0 to many -// nl = CR | CR_LF -// result-class ==> "done" | "running" | "connected" | "error" | "exit" -// result ==> variable "=" value -// value ==> const | tuple | list -// const ==> c-string (7 bit iso c string content) -// tuple ==> "{}" | "{" result ( "," result )* "}" -// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" -// More information see: -// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html -// Gotchas: None. -// Authors: Illya Rudkin 24/02/2014. -// Changes: None. +// Details: MI common code MI Result class. Part of the CMICmnMIValueResultRecord +// set of objects. +// The syntax is as follows: +// result-record ==> [ token ] "^" result-class ( "," result )* nl +// token = any sequence of digits +// * = 0 to many +// nl = CR | CR_LF +// result-class ==> "done" | "running" | "connected" | "error" | "exit" +// result ==> variable "=" value +// value ==> const | tuple | list +// const ==> c-string (7 bit iso c string content) +// tuple ==> "{}" | "{" result ( "," result )* "}" +// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" +// More information see: +// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html +// Gotchas: None. +// Authors: Illya Rudkin 24/02/2014. +// Changes: None. //-- class CMICmnMIValueResult : public CMICmnMIValue { -// Methods: -public: - /* ctor */ CMICmnMIValueResult( void ); - /* ctor */ CMICmnMIValueResult( const CMIUtilString & vVariable, const CMICmnMIValue & vValue ); - /* ctor */ CMICmnMIValueResult( const CMIUtilString & vVariable, const CMICmnMIValue & vValue, const bool vbUseSpacing ); - // - bool Add( const CMIUtilString & vVariable, const CMICmnMIValue & vValue ); + // Methods: + public: + /* ctor */ CMICmnMIValueResult(void); + /* ctor */ CMICmnMIValueResult(const CMIUtilString &vVariable, const CMICmnMIValue &vValue); + /* ctor */ CMICmnMIValueResult(const CMIUtilString &vVariable, const CMICmnMIValue &vValue, const bool vbUseSpacing); + // + bool Add(const CMIUtilString &vVariable, const CMICmnMIValue &vValue); -// Overridden: -public: - // From CMICmnBase - /* dtor */ virtual ~CMICmnMIValueResult( void ); + // Overridden: + public: + // From CMICmnBase + /* dtor */ virtual ~CMICmnMIValueResult(void); -// Methods: -private: - bool BuildResult( void ); - bool BuildResult( const CMIUtilString & vVariable, const CMICmnMIValue & vValue ); + // Methods: + private: + bool BuildResult(void); + bool BuildResult(const CMIUtilString &vVariable, const CMICmnMIValue &vValue); -// Attributes: -private: - static const CMIUtilString ms_constStrEqual; - // - CMIUtilString m_strPartVariable; - CMICmnMIValue m_partMIValue; - bool m_bEmptyConstruction; // True = *this object used constructor with no parameters, false = constructor with parameters - bool m_bUseSpacing; // True = put space seperators into the string, false = no spaces used + // Attributes: + private: + static const CMIUtilString ms_constStrEqual; + // + CMIUtilString m_strPartVariable; + CMICmnMIValue m_partMIValue; + bool m_bEmptyConstruction; // True = *this object used constructor with no parameters, false = constructor with parameters + bool m_bUseSpacing; // True = put space seperators into the string, false = no spaces used }; diff --git a/tools/lldb-mi/MICmnMIValueTuple.cpp b/tools/lldb-mi/MICmnMIValueTuple.cpp index 2f1349e79795..61fad88b5517 100644 --- a/tools/lldb-mi/MICmnMIValueTuple.cpp +++ b/tools/lldb-mi/MICmnMIValueTuple.cpp @@ -8,220 +8,225 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnMIValueTuple.h +// File: MICmnMIValueTuple.h // -// Overview: CMICmnMIValueTuple implementation. +// Overview: CMICmnMIValueTuple implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: #include "MICmnMIValueTuple.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValueTuple constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnMIValueTuple constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnMIValueTuple::CMICmnMIValueTuple( void ) -: m_bSpaceAfterComma( false ) +CMICmnMIValueTuple::CMICmnMIValueTuple(void) + : m_bSpaceAfterComma(false) { - m_strValue = "{}"; + m_strValue = "{}"; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValueTuple constructor. -// Type: Method. -// Args: vResult - (R) MI result object. -// Return: None. -// Throws: None. +// Details: CMICmnMIValueTuple constructor. +// Type: Method. +// Args: vResult - (R) MI result object. +// Return: None. +// Throws: None. //-- -CMICmnMIValueTuple::CMICmnMIValueTuple( const CMICmnMIValueResult & vResult ) -: m_bSpaceAfterComma( false ) +CMICmnMIValueTuple::CMICmnMIValueTuple(const CMICmnMIValueResult &vResult) + : m_bSpaceAfterComma(false) { - m_strValue = vResult.GetString(); - BuildTuple(); - m_bJustConstructed = false; + m_strValue = vResult.GetString(); + BuildTuple(); + m_bJustConstructed = false; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValueTuple constructor. -// Type: Method. -// Args: vResult - (R) MI result object. -// vbUseSpacing - (R) True = put space seperators into the string, false = no spaces used. -// Return: None. -// Throws: None. +// Details: CMICmnMIValueTuple constructor. +// Type: Method. +// Args: vResult - (R) MI result object. +// vbUseSpacing - (R) True = put space seperators into the string, false = no spaces used. +// Return: None. +// Throws: None. //-- -CMICmnMIValueTuple::CMICmnMIValueTuple( const CMICmnMIValueResult & vResult, const bool vbUseSpacing ) -: m_bSpaceAfterComma( vbUseSpacing ) +CMICmnMIValueTuple::CMICmnMIValueTuple(const CMICmnMIValueResult &vResult, const bool vbUseSpacing) + : m_bSpaceAfterComma(vbUseSpacing) { - m_strValue = vResult.GetString(); - BuildTuple(); - m_bJustConstructed = false; + m_strValue = vResult.GetString(); + BuildTuple(); + m_bJustConstructed = false; } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnMIValueTuple destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnMIValueTuple destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnMIValueTuple::~CMICmnMIValueTuple( void ) +CMICmnMIValueTuple::~CMICmnMIValueTuple(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Build the result value's mandatory data part, one tuple -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Build the result value's mandatory data part, one tuple +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIValueTuple::BuildTuple( void ) +bool +CMICmnMIValueTuple::BuildTuple(void) { - const MIchar * pFormat = "{%s}"; - m_strValue = CMIUtilString::Format( pFormat, m_strValue.c_str() ); - - return MIstatus::success; + const MIchar *pFormat = "{%s}"; + m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str()); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Add another MI result object to the value's list of tuples. -// Type: Method. -// Args: vResult - (R) The MI result object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Add another MI result object to the value's list of tuples. +// Type: Method. +// Args: vResult - (R) The MI result object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIValueTuple::BuildTuple( const CMICmnMIValueResult & vResult ) +bool +CMICmnMIValueTuple::BuildTuple(const CMICmnMIValueResult &vResult) { - // Clear out the default "" text - if( m_bJustConstructed ) - { - m_bJustConstructed = false; - m_strValue = vResult.GetString(); - return BuildTuple(); - } - - if( m_strValue[ 0 ] == '{' ) - { - m_strValue = m_strValue.substr( 1, m_strValue.size() - 1 ); - } - if( m_strValue[ m_strValue.size() - 1 ] == '}' ) - { - m_strValue = m_strValue.substr( 0, m_strValue.size() - 1 ); - } - - const MIchar * pFormat = m_bSpaceAfterComma ? "{%s, %s}" : "{%s,%s}"; - m_strValue = CMIUtilString::Format( pFormat, m_strValue.c_str(), vResult.GetString().c_str() ); - - return MIstatus::success; + // Clear out the default "" text + if (m_bJustConstructed) + { + m_bJustConstructed = false; + m_strValue = vResult.GetString(); + return BuildTuple(); + } + + if (m_strValue[0] == '{') + { + m_strValue = m_strValue.substr(1, m_strValue.size() - 1); + } + if (m_strValue[m_strValue.size() - 1] == '}') + { + m_strValue = m_strValue.substr(0, m_strValue.size() - 1); + } + + const MIchar *pFormat = m_bSpaceAfterComma ? "{%s, %s}" : "{%s,%s}"; + m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str(), vResult.GetString().c_str()); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Add string value to the value's list of tuples. -// Type: Method. -// Args: vValue - (R) The string object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Add string value to the value's list of tuples. +// Type: Method. +// Args: vValue - (R) The string object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIValueTuple::BuildTuple( const CMIUtilString & vValue ) +bool +CMICmnMIValueTuple::BuildTuple(const CMIUtilString &vValue) { - // Clear out the default "" text - if( m_bJustConstructed ) - { - m_bJustConstructed = false; - m_strValue = vValue; - return BuildTuple(); - } - - const CMIUtilString data( ExtractContentNoBrackets() ); - const MIchar * pFormat = m_bSpaceAfterComma ? "{%s, %s}" : "{%s,%s}"; - m_strValue = CMIUtilString::Format( pFormat, data.c_str(), vValue.c_str() ); - - return MIstatus::success; + // Clear out the default "" text + if (m_bJustConstructed) + { + m_bJustConstructed = false; + m_strValue = vValue; + return BuildTuple(); + } + + const CMIUtilString data(ExtractContentNoBrackets()); + const MIchar *pFormat = m_bSpaceAfterComma ? "{%s, %s}" : "{%s,%s}"; + m_strValue = CMIUtilString::Format(pFormat, data.c_str(), vValue.c_str()); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Add another MI value object to the value list's of list is values. -// Only values objects can be added to a list of values otherwise this function -// will return MIstatus::failure. -// Type: Method. -// Args: vValue - (R) The MI value object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Add another MI value object to the value list's of list is values. +// Only values objects can be added to a list of values otherwise this function +// will return MIstatus::failure. +// Type: Method. +// Args: vValue - (R) The MI value object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIValueTuple::Add( const CMICmnMIValueResult & vResult ) +bool +CMICmnMIValueTuple::Add(const CMICmnMIValueResult &vResult) { - return BuildTuple( vResult ); + return BuildTuple(vResult); } //++ ------------------------------------------------------------------------------------ -// Details: Add another MI value object to the value list's of list is values. -// Only values objects can be added to a list of values otherwise this function -// will return MIstatus::failure. -// Type: Method. -// Args: vValue - (R) The MI value object. -// vbUseSpacing - (R) True = put space seperators into the string, false = no spaces used. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Add another MI value object to the value list's of list is values. +// Only values objects can be added to a list of values otherwise this function +// will return MIstatus::failure. +// Type: Method. +// Args: vValue - (R) The MI value object. +// vbUseSpacing - (R) True = put space seperators into the string, false = no spaces used. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIValueTuple::Add( const CMICmnMIValueResult & vResult, const bool vbUseSpacing ) +bool +CMICmnMIValueTuple::Add(const CMICmnMIValueResult &vResult, const bool vbUseSpacing) { - m_bSpaceAfterComma = vbUseSpacing; - return BuildTuple( vResult ); + m_bSpaceAfterComma = vbUseSpacing; + return BuildTuple(vResult); } //++ ------------------------------------------------------------------------------------ -// Details: Add another MI value object to the value list's of list is values. -// Only values objects can be added to a list of values otherwise this function -// will return MIstatus::failure. -// Type: Method. -// Args: vValue - (R) The MI value object. -// vbUseSpacing - (R) True = put space seperators into the string, false = no spaces used. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Add another MI value object to the value list's of list is values. +// Only values objects can be added to a list of values otherwise this function +// will return MIstatus::failure. +// Type: Method. +// Args: vValue - (R) The MI value object. +// vbUseSpacing - (R) True = put space seperators into the string, false = no spaces used. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnMIValueTuple::Add( const CMICmnMIValueConst & vValue, const bool vbUseSpacing ) +bool +CMICmnMIValueTuple::Add(const CMICmnMIValueConst &vValue, const bool vbUseSpacing) { - m_bSpaceAfterComma = vbUseSpacing; - return BuildTuple( vValue.GetString() ); + m_bSpaceAfterComma = vbUseSpacing; + return BuildTuple(vValue.GetString()); } - //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the contents of *this value object but without the outer most -// brackets. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Data within the object. -// Throws: None. +// Details: Retrieve the contents of *this value object but without the outer most +// brackets. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Data within the object. +// Throws: None. //-- -CMIUtilString CMICmnMIValueTuple::ExtractContentNoBrackets( void ) const +CMIUtilString +CMICmnMIValueTuple::ExtractContentNoBrackets(void) const { - CMIUtilString data( m_strValue ); - - if( data[ 0 ] == '{' ) - { - data = data.substr( 1, data.length() - 1 ); - } - if( data[ data.size() - 1 ] == '}' ) - { - data = data.substr( 0, data.length() - 1 ); - } - - return data; + CMIUtilString data(m_strValue); + + if (data[0] == '{') + { + data = data.substr(1, data.length() - 1); + } + if (data[data.size() - 1] == '}') + { + data = data.substr(0, data.length() - 1); + } + + return data; } - diff --git a/tools/lldb-mi/MICmnMIValueTuple.h b/tools/lldb-mi/MICmnMIValueTuple.h index 0399c9d5068f..d5cc5326ea44 100644 --- a/tools/lldb-mi/MICmnMIValueTuple.h +++ b/tools/lldb-mi/MICmnMIValueTuple.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnMIValueTuple.h +// File: MICmnMIValueTuple.h // -// Overview: CMICmnMIValueTuple interface. +// Overview: CMICmnMIValueTuple interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -27,50 +27,50 @@ #include "MICmnMIValueConst.h" //++ ============================================================================ -// Details: MI common code MI Result class. Part of the CMICmnMIValueTupleRecord -// set of objects. -// The syntax is as follows: -// result-record ==> [ token ] "^" result-class ( "," result )* nl -// token = any sequence of digits -// * = 0 to many -// nl = CR | CR_LF -// result-class ==> "done" | "running" | "connected" | "error" | "exit" -// result ==> variable "=" value -// value ==> const | tuple | list -// const ==> c-string (7 bit iso c string content) -// tuple ==> "{}" | "{" result ( "," result )* "}" -// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" -// More information see: -// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html -// Gotchas: None. -// Authors: Illya Rudkin 24/02/2014. -// Changes: None. +// Details: MI common code MI Result class. Part of the CMICmnMIValueTupleRecord +// set of objects. +// The syntax is as follows: +// result-record ==> [ token ] "^" result-class ( "," result )* nl +// token = any sequence of digits +// * = 0 to many +// nl = CR | CR_LF +// result-class ==> "done" | "running" | "connected" | "error" | "exit" +// result ==> variable "=" value +// value ==> const | tuple | list +// const ==> c-string (7 bit iso c string content) +// tuple ==> "{}" | "{" result ( "," result )* "}" +// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" +// More information see: +// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html +// Gotchas: None. +// Authors: Illya Rudkin 24/02/2014. +// Changes: None. //-- class CMICmnMIValueTuple : public CMICmnMIValue { -// Methods: -public: - /* ctor */ CMICmnMIValueTuple( void ); - /* ctor */ CMICmnMIValueTuple( const CMICmnMIValueResult & vResult ); - /* ctor */ CMICmnMIValueTuple( const CMICmnMIValueResult & vResult, const bool vbUseSpacing ); - // - bool Add( const CMICmnMIValueResult & vResult ); - bool Add( const CMICmnMIValueResult & vResult, const bool vbUseSpacing ); - bool Add( const CMICmnMIValueConst & vValue, const bool vbUseSpacing ); - CMIUtilString ExtractContentNoBrackets( void ) const; + // Methods: + public: + /* ctor */ CMICmnMIValueTuple(void); + /* ctor */ CMICmnMIValueTuple(const CMICmnMIValueResult &vResult); + /* ctor */ CMICmnMIValueTuple(const CMICmnMIValueResult &vResult, const bool vbUseSpacing); + // + bool Add(const CMICmnMIValueResult &vResult); + bool Add(const CMICmnMIValueResult &vResult, const bool vbUseSpacing); + bool Add(const CMICmnMIValueConst &vValue, const bool vbUseSpacing); + CMIUtilString ExtractContentNoBrackets(void) const; -// Overridden: -public: - // From CMICmnBase - /* dtor */ virtual ~CMICmnMIValueTuple( void ); + // Overridden: + public: + // From CMICmnBase + /* dtor */ virtual ~CMICmnMIValueTuple(void); -// Methods: -private: - bool BuildTuple( void ); - bool BuildTuple( const CMICmnMIValueResult & vResult ); - bool BuildTuple( const CMIUtilString & vValue ); + // Methods: + private: + bool BuildTuple(void); + bool BuildTuple(const CMICmnMIValueResult &vResult); + bool BuildTuple(const CMIUtilString &vValue); -// Attributes: -private: - bool m_bSpaceAfterComma; // True = put space seperators into the string, false = no spaces used + // Attributes: + private: + bool m_bSpaceAfterComma; // True = put space seperators into the string, false = no spaces used }; diff --git a/tools/lldb-mi/MICmnResources.cpp b/tools/lldb-mi/MICmnResources.cpp index 08ac2f0edfe0..676e9e743986 100644 --- a/tools/lldb-mi/MICmnResources.cpp +++ b/tools/lldb-mi/MICmnResources.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnResources.cpp +// File: MICmnResources.cpp // -// Overview: CMICmnResources implementation. +// Overview: CMICmnResources implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third party headers @@ -26,384 +26,411 @@ #include "MICmnResources.h" // Instantiations: -const CMICmnResources::SRsrcTextData CMICmnResources::ms_pResourceId2TextData[] = -{ - { IDS_PROJNAME, "LLDB Machine Interface Driver (MI) All rights reserved" }, - { IDS_MI_VERSION_DESCRIPTION_DEBUG, "Version: 1.0.0.9 (Debug)" }, // See version history in MIDriverMain.cpp - { IDS_MI_VERSION_DESCRIPTION, "Version: 1.0.0.9" }, - { IDS_MI_APPNAME_SHORT, "MI" }, - { IDS_MI_APPNAME_LONG, "Machine Interface Driver" }, - { IDS_MI_APP_FILEPATHNAME, "Application: %s" }, - { IDS_MI_APP_ARGS, "Command line args: " }, - { IDE_MI_VERSION_GDB, "Version: GNU gdb (GDB) 7.4 \n(This is a MI stub on top of LLDB and not GDB)\nAll rights reserved.\n" }, // *** Eclipse needs this exactly!! - { IDS_UTIL_FILE_ERR_INVALID_PATHNAME, "File Handler. Invalid file name path" }, - { IDS_UTIL_FILE_ERR_OPENING_FILE, "File Handler. Error %s opening '%s'" }, - { IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN, "File Handler. Unknown error opening '%s'" }, - { IDE_UTIL_FILE_ERR_WRITING_FILE, "File Handler. Error %s writing '%s'" }, - { IDE_UTIL_FILE_ERR_WRITING_NOTOPEN, "File Handler. File '%s' not open for write" }, - { IDS_RESOURCES_ERR_STRING_NOT_FOUND, "Resources. String (%d) not found in resources" }, - { IDS_RESOURCES_ERR_STRING_TABLE_INVALID, "Resources. String resource table is not set up" }, - { IDS_MI_CLIENT_MSG, "Client message: \"%s\"" }, - { IDS_LOG_MSG_CREATION_DATE, "Creation date %s time %s%s" }, - { IDS_LOG_MSG_FILE_LOGGER_PATH, "File logger path: %s%s" }, - { IDS_LOG_MSG_VERSION, "Version: %s%s" }, - { IDS_LOG_ERR_FILE_LOGGER_DISABLED, "Log. File logger temporarily disabled due to file error '%s'" }, - { IDS_LOG_MEDIUM_ERR_INIT, "Log. Medium '%s' initialise failed. %s" }, - { IDS_LOG_MEDIUM_ERR_WRITE_ANY, "Log. Failed to write log data to any medium." }, - { IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL, "Log. One or mediums failed writing log data." }, - { IDS_MEDIUMFILE_NAME, "File" }, - { IDS_MEDIUMFILE_ERR_INVALID_PATH, "" }, - { IDS_MEDIUMFILE_ERR_FILE_HEADER, "" }, - { IDS_MEDIUMFILE_NAME_LOG, "File medium. %s" }, - { IDE_MEDIUMFILE_ERR_GET_FILE_PATHNAME_SYS, "File Medium. Failed to retrieve the system/executable path for the Log file" }, - { IDE_OS_ERR_UNKNOWN, "Unknown OS error" }, - { IDE_OS_ERR_RETRIEVING, "Unabled to retrieve OS error message" }, - { IDS_DRIVERMGR_DRIVER_ERR_INIT, "Driver Manager. Driver '%s' (ID:'%s') initialise failed. %s" }, - { IDE_MEDIUMSTDERR_NAME, "Stderr" }, - { IDE_MEDIUMSTDOUT_NAME, "Stdout" }, - { IDE_MI_APP_EXIT_OK, "Program exited OK" }, - { IDE_MI_APP_EXIT_WITH_PROBLEM, "Program exited with a problem, see '%s' file" }, - { IDE_MI_APP_EXIT_WITH_PROBLEM_NO_LOG, "Program exited with a problem, the application's log file '%s' was disabled" }, - { IDE_MI_APP_DESCRIPTION, "Description:\nThe Machine Interface Driver (MI Driver) is a stand alone executable\nthat either be used via a client i.e. Eclipse or directly from the command\nline. It processes MI commands, actions those commands using the internal\ndebugger then forms MI response formatted text which is returned to the\nclient." }, - { IDE_MI_APP_INFORMATION, "Information:\nCurrent limitations. The MI Driver currently only handles remote target\ndebugging. Local debugging has not been implemented. The MI Driver has\nbeen designed primarily to be used with Eclipse Juno and a custom plugin.\nThe custom plugin is not necessary to operate the MI Driver." }, - { IDE_MI_APP_ARG_USAGE, "\nMI driver usage:\n\n\tlldb-mi [--longOption] [-s hortOption] [executeable]\n\n[] = optional argument." }, - { IDE_MI_APP_ARG_HELP, "-h\n--help\n\tPrints out usage information for the MI debugger. Exit the MI\n\tDriver immediately." }, - { IDE_MI_APP_ARG_VERSION, "--version\n\tPrints out GNU (gdb) version information. Exit the MI Driver\n\timmediately." }, - { IDE_MI_APP_ARG_VERSION_LONG, "--versionLong\n\tPrints out MI Driver version information. Exit the MI Driver\n\timmediately." }, - { IDE_MI_APP_ARG_INTERPRETER, "--interpreter\n\tUse the MI Driver for the debugger (MI mode)(Default is the\n\tLLDB driver). Any LLDB command line options are ignored even\n\tif the MI Driver falls through to the LLDB driver. (Depends\n\ton the build configuration see MICmnConfig.h)\n\tNormally specified by the driver client i.e. Eclipse.\n\tCannot specify an executable with this option, use --executable." }, - { IDE_MI_APP_ARG_EXECUTEABLE, "--executable\n\tUse the MI Driver in MI mode for the debugging the specified\n\texecutable. Any LLDB command line options are ignored even\n\tif the MI Driver falls through to the LLDB driver. (Depends\n\ton the build configuration see MICmnConfig.h)\n\tNormally specified from the command line." }, - { IDE_MI_APP_ARG_NO_APP_LOG, "--noLog\n\tUse this argument to tell the MI Driver not to update it's log\n\tfile '%s'." }, - { IDE_MI_APP_ARG_EXAMPLE, "Example MI command:\n\t3-info-gdb-mi-command gdb-set\n\t3^done,command={exists=\"true\"}" }, - { IDE_MI_APP_ARG_EXECUTABLE, "executable (NOT IMPLEMENTED)\n\tThe file path to the executable i.e. '\"C:\\My Dev\\foo.exe\"'." }, - { IDS_STDIN_ERR_INVALID_PROMPT, "Stdin. Invalid prompt description '%s'" }, - { IDS_STDIN_ERR_THREAD_CREATION_FAILED, "Stdin. Thread creation failed '%s'" }, - { IDS_STDIN_ERR_THREAD_DELETE, "Stdin. Thread failed to delete '%s'" }, - { IDS_STDIN_ERR_CHKING_BYTE_AVAILABLE, "Stdin. Peeking on stdin stream '%s'" }, - { IDS_STDIN_INPUT_CTRL_CHARS, "Stdin. Receive characters not handled as a command: " }, - { IDS_CMD_QUIT_HELP, "MI Driver Command: quit\n\tExit the MI Driver application." }, - { IDS_THREADMGR_ERR_THREAD_ID_INVALID, "Thread Mgr. Thread ID '%s' is not valid" }, - { IDS_THREADMGR_ERR_THREAD_FAIL_CREATE, "Thread Mgr: Failed to create thread '%s'" }, - { IDS_THREADMGR_ERR_THREAD_ID_NOT_FOUND, "Thread Mgr: Thread with ID '%s' not found" }, - { IDS_THREADMGR_ERR_THREAD_STILL_ALIVE, "Thread Mgr: The thread(s) are still alive at Thread Mgr shutdown: %s" }, - { IDS_FALLTHRU_DRIVER_CMD_RECEIVED, "Fall Thru Driver. Received command '%s'. Is was %shandled" }, - { IDS_CMDFACTORY_ERR_INVALID_CMD_NAME, "Command factory. MI command name '%s' is invalid" }, - { IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN, "Command factory. Command creation function invalid for command '%s'. Does function exist? Pointer assigned to it?" }, - { IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED, "Command factory. Command '%s' not registered" }, - { IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED, "Command factory. Command '%s' by that name already registered" }, - { IDS_CMDMGR_ERR_CMD_FAILED_CREATE, "Command manager. Command creation failed. %s" }, - { IDS_CMDMGR_ERR_CMD_INVOKER, "Command manager. %s " }, - { IDS_PROCESS_SIGNAL_RECEIVED, "Process signal. Application received signal '%s' (%d)" }, - { IDS_MI_INIT_ERR_LOG, "Log. Error occurred during initialisation %s" }, - { IDS_MI_INIT_ERR_RESOURCES, "Resources. Error occurred during initialisation %s" }, - { IDS_MI_INIT_ERR_INIT, "Driver. Error occurred during initialisation %s" }, - { IDS_MI_INIT_ERR_STREAMSTDIN, "Stdin. Error occurred during initialisation %s" }, - { IDS_MI_INIT_ERR_STREAMSTDIN_OSHANDLER, "Stdin. The OS specific stdin stream handler has not been specified for this OS" }, - { IDS_MI_INIT_ERR_OS_STDIN_HANDLER, "Stdin handler. Error occurred during initialisation %s" }, - { IDS_MI_INIT_ERR_STREAMSTDOUT, "Stdout. Error occurred during initialisation %s" }, - { IDS_MI_INIT_ERR_STREAMSTDERR, "Stderr. Error occurred during initialisation %s" }, - { IDS_MI_INIT_ERR_FALLTHRUDRIVER, "Fall Through Driver. Error occurred during initialisation %s" }, - { IDS_MI_INIT_ERR_THREADMGR, "Thread Mgr. Error occurred during initialisation %s" }, - { IDS_MI_INIT_ERR_CMDINTERPRETER, "Command interpreter. %s" }, - { IDS_MI_INIT_ERR_CMDMGR, "Command manager. %s" }, - { IDS_MI_INIT_ERR_CMDFACTORY, "Command factory. %s" }, - { IDS_MI_INIT_ERR_CMDINVOKER, "Command invoker. %s" }, - { IDS_MI_INIT_ERR_CMDMONITOR, "Command monitor. %s" }, - { IDS_MI_INIT_ERR_LLDBDEBUGGER, "LLDB Debugger. %s" }, - { IDS_MI_INIT_ERR_DRIVERMGR, "Driver manager. %s" }, - { IDS_MI_INIT_ERR_DRIVER, "Driver. %s" }, - { IDS_MI_INIT_ERR_OUTOFBANDHANDLER, "Out-of-band handler. %s " }, - { IDS_MI_INIT_ERR_DEBUGSESSIONINFO, "LLDB debug session info. %s " }, - { IDS_MI_INIT_ERR_THREADMANAGER, "Unable to init thread manager." }, - { IDS_MI_INIT_ERR_CLIENT_USING_DRIVER, "Initialising the client to this driver failed." }, - { IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION, "Initialising a local debug session failed." }, - { IDS_CODE_ERR_INVALID_PARAMETER_VALUE, "Code. Invalid parameter passed to function '%s'" }, - { IDS_CODE_ERR_INVALID_PARAM_NULL_POINTER, "Code. NULL pointer passes as a parameter to function '%s'" }, - { IDS_CODE_ERR_INVALID_ENUMERATION_VALUE, "Code. Invalid enumeration value encountered in function '%s'" }, - { IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER, "LLDB Debugger. LLDB Listener is not valid", }, - { IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER, "LLDB Debugger. LLDB Debugger is not valid", }, - { IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER, "LLDB Debugger. CMIDriverBase derived driver needs to be set prior to CMICmnLLDBDDebugger initialisation" }, - { IDS_LLDBDEBUGGER_ERR_STARTLISTENER, "LLDB Debugger. Starting listening events for '%s' failed" }, - { IDS_LLDBDEBUGGER_ERR_THREADCREATIONFAIL, "LLDB Debugger. Thread creation failed '%s'" }, - { IDS_LLDBDEBUGGER_ERR_THREAD_DELETE, "LLDB Debugger. Thread failed to delete '%s'" }, - { IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER, "LLDB Debugger. Invalid SB broadcaster class name '%s' " }, - { IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME, "LLDB Debugger. Invalid client name '%s' " }, - { IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERD, "LLDB Debugger. Client name '%s' not registered for listening events" }, - { IDS_LLDBDEBUGGER_ERR_STOPLISTENER, "LLDB Debugger. Failure occurred stopping event for client '%s' SBBroadcaster '%s'" }, - { IDS_LLDBDEBUGGER_ERR_BROARDCASTER_NAME, "LLDB Debugger. Broardcaster's name '%s' is not valid" }, - { IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT, "LLDB Debugger. Unhandled event '%s'" }, - { IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT, "LLDB Out-of-band. Handling event for '%s', an event enumeration '%d' not recognised" }, - { IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID, "LLDB Out-of-band. Invalid '%s' in '%s'" }, - { IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND, "LLDB Out-of-band. %s. Breakpoint information for breakpoint ID %d not found" }, - { IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET, "LLDB Out-of-band. %s. Failed to retrieve breakpoint information for for breakpoint ID %d" }, - { IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET, "LLDB Out-of-band. %s. Failed to set breakpoint information for for breakpoint ID %d" }, - { IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE, "LLDB Out-of-band. %s. Failed to form the MI Out-of-band response" }, - { IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET, "LLDB Out-of-band. %s. Failed to retrieve frame information" }, - { IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE, "LLDB Out-of-band. %s. Event handler tried to set new MI Driver running state and failed. %s" }, - { IDS_LLDBOUTOFBAND_ERR_BRKPT_CNT_EXCEEDED, "LLDB Out-of-band. '%s'. Number of valid breakpoint exceeded %d. Cannot create new breakpoint with ID %d" }, - { IDS_DBGSESSION_ERR_SHARED_DATA_RELEASE, "LLDB debug session info. Release some or all of the data shared across command instances failed" }, - { IDS_DBGSESSION_ERR_SHARED_DATA_ADD, "LLDB debug session info. Failed to add '%s' data to the shared data command container" }, - { IDS_MI_SHTDWN_ERR_LOG, "Log. Error occurred during shutdown. %s" }, - { IDS_MI_SHUTDOWN_ERR, "Server shutdown failure. %s" }, - { IDE_MI_SHTDWN_ERR_RESOURCES, "Resources. Error occurred during shutdown. %s" }, - { IDE_MI_SHTDWN_ERR_STREAMSTDIN, "Stdin. Error occurred during shutdown. %s" }, - { IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, "Stdin handler. Error occurred during shutdown. %s" }, - { IDS_MI_SHTDWN_ERR_STREAMSTDOUT, "Stdout. Error occurred during shutdown. %s" }, - { IDS_MI_SHTDWN_ERR_STREAMSTDERR, "Stderr. Error occurred during shutdown. %s" }, - { IDS_MI_SHTDWN_ERR_THREADMGR, "Thread Mgr. Error occurred during shutdown. %s" }, - { IDS_MI_SHTDWN_ERR_CMDINTERPRETER, "Command interpreter. Error occurred during shutdown. %s" }, - { IDS_MI_SHTDWN_ERR_CMDMGR, "Command manager. Error occurred during shutdown. %s" }, - { IDS_MI_SHTDWN_ERR_CMDFACTORY, "Command factory. Error occurred during shutdown. %s" }, - { IDS_MI_SHTDWN_ERR_CMDMONITOR, "Command invoker. Error occurred during shutdown. %s" }, - { IDS_MI_SHTDWN_ERR_CMDINVOKER, "Command monitor. Error occurred during shutdown. %s" }, - { IDS_MI_SHTDWN_ERR_LLDBDEBUGGER, "LLDB Debugger. Error occurred during shutdown. %s" }, - { IDS_MI_SHTDWN_ERR_DRIVERMGR, "Driver manager. Error occurred during shutdown. %s" }, - { IDS_MI_SHTDWN_ERR_DRIVER, "Driver. Error occurred during shutdown. %s" }, - { IDS_MI_SHTDWN_ERR_OUTOFBANDHANDLER, "Out-of-band handler. Error occurred during shutdown. %s" }, - { IDS_MI_SHTDWN_ERR_DEBUGSESSIONINFO, "LLDB debug session info. Error occurred during shutdown. %s" }, - { IDE_MI_SHTDWN_ERR_THREADMANAGER, "Unable to shutdown thread manager" }, - { IDS_DRIVER_ERR_PARSE_ARGS, "Driver. Driver '%s'. Parse args error '%s'" }, - { IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN, "Driver. Driver '%s'. Parse args error unknown" }, - { IDS_DRIVER_ERR_CURRENT_NOT_SET, "Driver. Current working driver has not been set. Call CMIDriverMgr::SetUseThisDriverToDoWork()" }, - { IDS_DRIVER_ERR_NON_REGISTERED, "Driver. No suitable drivers registered with the CMIDriverMgr to do work" }, - { IDS_DRIVER_SAY_DRIVER_USING, "Driver. Using driver '%s' internally" }, - { IDS_DRIVER_ERR_ID_INVALID, "Driver. Driver '%s' invalid ID '%s'" }, - { IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR, "Driver. Fall through driver '%s' (ID:'%s') error '%s'" }, - { IDS_DRIVER_CMD_RECEIVED, "Driver. Received command '%s'. It was %shandled%s" }, - { IDS_DRIVER_CMD_NOT_IN_FACTORY, ". Command '%s' not in Command Factory" }, - { IDS_DRIVER_ERR_DRIVER_STATE_ERROR, "Driver. Driver running state error. Cannot go to next state from present state as not allowed", }, - { IDS_DRIVER_WAITING_STDIN_DATA, "Driver. Main thread suspended waiting on Stdin Monitor to resume main thread" }, - { IDS_DRIVER_ERR_MAINLOOP, "Driver. Error in do main loop. %s" }, - { IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL, "Driver. --executable argument given. Local debugging is not implemented." }, - { IDS_DRIVER_ERR_LOCAL_DEBUG_INIT, "Driver. --executable argument given. Initialising local debugging failed." }, - { IDS_STDOUT_ERR_NOT_ALL_DATA_WRITTEN, "Stdout. Not all data was written to stream. The data '%s'" }, - { IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN, "Stderr. Not all data was written to stream. The data '%s'" }, - { IDS_CMD_ARGS_ERR_N_OPTIONS_REQUIRED, "Command Args. Missing options, %d or more required" }, - { IDS_CMD_ARGS_ERR_OPTION_NOT_FOUND, "Command Args. Option '%s' not found" }, - { IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY, "Mandatory args not found: %s" }, - { IDS_CMD_ARGS_ERR_VALIDATION_INVALID, "Invalid args: %s" }, - { IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID, "Mandatory args not found: %s. Invalid args: %s" }, - { IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF, "Args missing additional information: %s" }, - { IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN, "Not all arguments or options were recognised: %s" }, - { IDS_CMD_ARGS_ERR_PREFIX_MSG, "Command Args. Validation failed. " }, - { IDS_VARIANT_ERR_USED_BASECLASS, "Variant container: Variant object used the base class. See CMIUtilVariant" }, - { IDS_VARIANT_ERR_MAP_KEY_INVALID, "Variant container: Invalid ID '%s'" }, - { IDS_WORD_INVALIDBRKTS, "" }, - { IDS_WORD_NONE, "None" }, - { IDS_WORD_NOT, "not" }, - { IDS_WORD_INVALIDEMPTY, "" }, - { IDS_WORD_INVALIDNULLPTR, "" }, - { IDS_WORD_UNKNOWNBRKTS, "" }, - { IDS_WORD_NOT_IMPLEMENTED, "Not implemented" }, - { IDS_WORD_NOT_IMPLEMENTED_BRKTS, "" }, - { IDS_WORD_UNKNOWNTYPE_BRKTS, "" }, - { IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS, "" }, - { IDS_CMD_ERR_N_OPTIONS_REQUIRED, "Command '%s'. Missing options, %d required" }, - { IDS_CMD_ERR_OPTION_NOT_FOUND, "Command '%s'. Option '%s' not found" }, - { IDS_CMD_ERR_ARGS, "Command '%s'. %s" }, - { IDS_CMD_WRN_ARGS_NOT_HANDLED, "Command '%s'. Warning the following options not handled by the command: %s" }, - { IDS_CMD_ERR_FNFAILED, "Command '%s'. Fn '%s' failed" }, - { IDS_CMD_ERR_SHARED_DATA_NOT_FOUND, "Command '%s'. Shared data '%s' not found" }, - { IDS_CMD_ERR_LLDBPROCESS_DETACH, "Command '%s'. Process detach failed. '%s'" }, - { IDS_CMD_ERR_SETWKDIR, "Command '%s'. Failed to set working directory '%s'" }, - { IDS_CMD_ERR_INVALID_TARGET, "Command '%s'. Target binary '%s' is invalid. %s" }, - { IDS_CMD_ERR_INVALID_TARGET_CURRENT, "Command '%s'. Current SBTarget is invalid" }, - { IDS_CMD_ERR_INVALID_TARGET_TYPE, "Command '%s'. Target type '%s' is not recognised" }, - { IDS_CMD_ERR_INVALID_TARGET_PLUGIN, "Command '%s'. Target plugin is invalid. %s" }, - { IDS_CMD_ERR_CONNECT_TO_TARGET, "Command '%s'. Error connecting to target: '%s'" }, - { IDS_CMD_ERR_INVALID_TARGETPLUGINCURRENT, "Command '%s'. Current target plugin is invalid" }, - { IDS_CMD_ERR_NOT_IMPLEMENTED, "Command '%s'. Command not implemented" }, - { IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED, "Command '%s'. Command not implemented as it has been deprecated" }, - { IDS_CMD_ERR_CREATE_TARGET, "Command '%s'. Create target failed: %s" }, - { IDS_CMD_ERR_BRKPT_LOCATION_FORMAT, "Command '%s'. Incorrect format for breakpoint location '%s'" }, - { IDS_CMD_ERR_BRKPT_INVALID, "Command '%s'. Breakpoint '%s' invalid" }, - { IDS_CMD_ERR_BRKPT_CNT_EXCEEDED, "Command '%s'. Number of valid breakpoint exceeded %d. Cannot create new breakpoint '%s'" }, - { IDS_CMD_ERR_SOME_ERROR, "Command '%s'. Error: %s" }, - { IDS_CMD_ERR_THREAD_INVALID, "Command '%s'. Thread ID invalid" }, - { IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID, "Command '%s'. Thread frame range invalid" }, - { IDS_CMD_ERR_FRAME_INVALID, "Command '%s'. Frame ID invalid" }, - { IDS_CMD_ERR_VARIABLE_DOESNOTEXIST, "Command '%s'. Variable '%s' does not exist" }, - { IDS_CMD_ERR_VARIABLE_ENUM_INVALID, "Command '%s'. Invalid enumeration for variable '%s' formatted string '%s'" }, - { IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH, "Command '%s'. Failed to get expression for variable '%s'" }, - { IDS_CMD_ERR_VARIABLE_CREATION_FAILED, "Failed to create variable object for '%s'" }, - { IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION, "" }, - { IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION, ""}, - { IDS_CMD_ERR_DISASM_ADDR_START_INVALID, "Command '%s'. Invalid start value '%s'" }, - { IDS_CMD_ERR_DISASM_ADDR_END_INVALID, "Command '%s'. Invalid end value '%s'" }, - { IDS_CMD_ERR_MEMORY_ALLOC_FAILURE, "Command '%s'. Failed to allocate memory %d bytes" }, - { IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK, "Command '%s'. LLDB unable to read entire memory block of %u bytes at address 0x%08x" }, - { IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES, "Command '%s'. Unable to read memory block of %u bytes at address 0x%08x: %s " }, - { IDS_CMD_ERR_INVALID_PROCESS, "Command '%s'. Invalid process during debug session" }, - { IDS_CMD_ERR_INVALID_FORMAT_TYPE, "Command '%s'. Invalid var format type '%s'" }, - { IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND, "Command '%s'. Breakpoint information for breakpoint ID %d not found" }, - { IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES, "Command '%s'. Unable to write memory block of %u bytes at address 0x%08x: %s " }, - { IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK, "Command '%s'. LLDB unable to write entire memory block of %u bytes at address 0x%08x" }, - { IDS_CMD_ERR_SET_NEW_DRIVER_STATE, "Command '%s'. Command tried to set new MI Driver running state and failed. %s" }, - { IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND, "The request '%s' was not recogised, not implemented" }, - { IDS_CMD_ERR_INFO_PRINTFN_FAILED, "The request '%s' failed." }, - { IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH, "'solib-search-path' requires at least one argument" } - }; +const CMICmnResources::SRsrcTextData CMICmnResources::ms_pResourceId2TextData[] = { + {IDS_PROJNAME, "LLDB Machine Interface Driver (MI) All rights reserved"}, + {IDS_MI_VERSION_DESCRIPTION_DEBUG, "Version: 1.0.0.9 (Debug)"}, // See version history in MIDriverMain.cpp + {IDS_MI_VERSION_DESCRIPTION, "Version: 1.0.0.9"}, + {IDS_MI_APPNAME_SHORT, "MI"}, + {IDS_MI_APPNAME_LONG, "Machine Interface Driver"}, + {IDS_MI_APP_FILEPATHNAME, "Application: %s"}, + {IDS_MI_APP_ARGS, "Command line args: "}, + {IDE_MI_VERSION_GDB, + "Version: GNU gdb (GDB) 7.4 \n(This is a MI stub on top of LLDB and not GDB)\nAll rights reserved.\n"}, // *** Eclipse needs this + // exactly!! + {IDS_UTIL_FILE_ERR_INVALID_PATHNAME, "File Handler. Invalid file name path"}, + {IDS_UTIL_FILE_ERR_OPENING_FILE, "File Handler. Error %s opening '%s'"}, + {IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN, "File Handler. Unknown error opening '%s'"}, + {IDE_UTIL_FILE_ERR_WRITING_FILE, "File Handler. Error %s writing '%s'"}, + {IDE_UTIL_FILE_ERR_WRITING_NOTOPEN, "File Handler. File '%s' not open for write"}, + {IDS_RESOURCES_ERR_STRING_NOT_FOUND, "Resources. String (%d) not found in resources"}, + {IDS_RESOURCES_ERR_STRING_TABLE_INVALID, "Resources. String resource table is not set up"}, + {IDS_MI_CLIENT_MSG, "Client message: \"%s\""}, + {IDS_LOG_MSG_CREATION_DATE, "Creation date %s time %s%s"}, + {IDS_LOG_MSG_FILE_LOGGER_PATH, "File logger path: %s%s"}, + {IDS_LOG_MSG_VERSION, "Version: %s%s"}, + {IDS_LOG_ERR_FILE_LOGGER_DISABLED, "Log. File logger temporarily disabled due to file error '%s'"}, + {IDS_LOG_MEDIUM_ERR_INIT, "Log. Medium '%s' initialise failed. %s"}, + {IDS_LOG_MEDIUM_ERR_WRITE_ANY, "Log. Failed to write log data to any medium."}, + {IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL, "Log. One or mediums failed writing log data."}, + {IDS_MEDIUMFILE_NAME, "File"}, + {IDS_MEDIUMFILE_ERR_INVALID_PATH, ""}, + {IDS_MEDIUMFILE_ERR_FILE_HEADER, ""}, + {IDS_MEDIUMFILE_NAME_LOG, "File medium. %s"}, + {IDE_MEDIUMFILE_ERR_GET_FILE_PATHNAME_SYS, "File Medium. Failed to retrieve the system/executable path for the Log file"}, + {IDE_OS_ERR_UNKNOWN, "Unknown OS error"}, + {IDE_OS_ERR_RETRIEVING, "Unabled to retrieve OS error message"}, + {IDS_DRIVERMGR_DRIVER_ERR_INIT, "Driver Manager. Driver '%s' (ID:'%s') initialise failed. %s"}, + {IDE_MEDIUMSTDERR_NAME, "Stderr"}, + {IDE_MEDIUMSTDOUT_NAME, "Stdout"}, + {IDE_MI_APP_EXIT_OK, "Program exited OK"}, + {IDE_MI_APP_EXIT_WITH_PROBLEM, "Program exited with a problem, see '%s' file"}, + {IDE_MI_APP_EXIT_WITH_PROBLEM_NO_LOG, "Program exited with a problem, the application's log file '%s' was disabled"}, + {IDE_MI_APP_DESCRIPTION, "Description:\nThe Machine Interface Driver (MI Driver) is a stand alone executable\nthat either be used via " + "a client i.e. Eclipse or directly from the command\nline. It processes MI commands, actions those commands " + "using the internal\ndebugger then forms MI response formatted text which is returned to the\nclient."}, + {IDE_MI_APP_INFORMATION, "Information:\nCurrent limitations. The MI Driver currently only handles remote target\ndebugging. Local " + "debugging has not been implemented. The MI Driver has\nbeen designed primarily to be used with Eclipse Juno " + "and a custom plugin.\nThe custom plugin is not necessary to operate the MI Driver."}, + {IDE_MI_APP_ARG_USAGE, "\nMI driver usage:\n\n\tlldb-mi [--longOption] [-s hortOption] [executeable]\n\n[] = optional argument."}, + {IDE_MI_APP_ARG_HELP, "-h\n--help\n\tPrints out usage information for the MI debugger. Exit the MI\n\tDriver immediately."}, + {IDE_MI_APP_ARG_VERSION, "--version\n\tPrints out GNU (gdb) version information. Exit the MI Driver\n\timmediately."}, + {IDE_MI_APP_ARG_VERSION_LONG, "--versionLong\n\tPrints out MI Driver version information. Exit the MI Driver\n\timmediately."}, + {IDE_MI_APP_ARG_INTERPRETER, "--interpreter\n\tUse the MI Driver for the debugger (MI mode)(Default is the\n\tLLDB driver). Any LLDB " + "command line options are ignored even\n\tif the MI Driver falls through to the LLDB driver. " + "(Depends\n\ton the build configuration see MICmnConfig.h)\n\tNormally specified by the driver client " + "i.e. Eclipse.\n\tCannot specify an executable with this option, use --executable."}, + {IDE_MI_APP_ARG_EXECUTEABLE, "--executable\n\tUse the MI Driver in MI mode for the debugging the specified\n\texecutable. Any LLDB " + "command line options are ignored even\n\tif the MI Driver falls through to the LLDB driver. " + "(Depends\n\ton the build configuration see MICmnConfig.h)\n\tNormally specified from the command line."}, + {IDE_MI_APP_ARG_NO_APP_LOG, "--noLog\n\tUse this argument to tell the MI Driver not to update it's log\n\tfile '%s'."}, + {IDE_MI_APP_ARG_EXAMPLE, "Example MI command:\n\t3-info-gdb-mi-command gdb-set\n\t3^done,command={exists=\"true\"}"}, + {IDE_MI_APP_ARG_EXECUTABLE, "executable (NOT IMPLEMENTED)\n\tThe file path to the executable i.e. '\"C:\\My Dev\\foo.exe\"'."}, + {IDS_STDIN_ERR_INVALID_PROMPT, "Stdin. Invalid prompt description '%s'"}, + {IDS_STDIN_ERR_THREAD_CREATION_FAILED, "Stdin. Thread creation failed '%s'"}, + {IDS_STDIN_ERR_THREAD_DELETE, "Stdin. Thread failed to delete '%s'"}, + {IDS_STDIN_ERR_CHKING_BYTE_AVAILABLE, "Stdin. Peeking on stdin stream '%s'"}, + {IDS_STDIN_INPUT_CTRL_CHARS, "Stdin. Receive characters not handled as a command: "}, + {IDS_CMD_QUIT_HELP, "MI Driver Command: quit\n\tExit the MI Driver application."}, + {IDS_THREADMGR_ERR_THREAD_ID_INVALID, "Thread Mgr. Thread ID '%s' is not valid"}, + {IDS_THREADMGR_ERR_THREAD_FAIL_CREATE, "Thread Mgr: Failed to create thread '%s'"}, + {IDS_THREADMGR_ERR_THREAD_ID_NOT_FOUND, "Thread Mgr: Thread with ID '%s' not found"}, + {IDS_THREADMGR_ERR_THREAD_STILL_ALIVE, "Thread Mgr: The thread(s) are still alive at Thread Mgr shutdown: %s"}, + {IDS_FALLTHRU_DRIVER_CMD_RECEIVED, "Fall Thru Driver. Received command '%s'. Is was %shandled"}, + {IDS_CMDFACTORY_ERR_INVALID_CMD_NAME, "Command factory. MI command name '%s' is invalid"}, + {IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN, + "Command factory. Command creation function invalid for command '%s'. Does function exist? Pointer assigned to it?"}, + {IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED, "Command factory. Command '%s' not registered"}, + {IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED, "Command factory. Command '%s' by that name already registered"}, + {IDS_CMDMGR_ERR_CMD_FAILED_CREATE, "Command manager. Command creation failed. %s"}, + {IDS_CMDMGR_ERR_CMD_INVOKER, "Command manager. %s "}, + {IDS_PROCESS_SIGNAL_RECEIVED, "Process signal. Application received signal '%s' (%d)"}, + {IDS_MI_INIT_ERR_LOG, "Log. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_RESOURCES, "Resources. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_INIT, "Driver. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_STREAMSTDIN, "Stdin. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_STREAMSTDIN_OSHANDLER, "Stdin. The OS specific stdin stream handler has not been specified for this OS"}, + {IDS_MI_INIT_ERR_OS_STDIN_HANDLER, "Stdin handler. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_STREAMSTDOUT, "Stdout. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_STREAMSTDERR, "Stderr. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_FALLTHRUDRIVER, "Fall Through Driver. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_THREADMGR, "Thread Mgr. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_CMDINTERPRETER, "Command interpreter. %s"}, + {IDS_MI_INIT_ERR_CMDMGR, "Command manager. %s"}, + {IDS_MI_INIT_ERR_CMDFACTORY, "Command factory. %s"}, + {IDS_MI_INIT_ERR_CMDINVOKER, "Command invoker. %s"}, + {IDS_MI_INIT_ERR_CMDMONITOR, "Command monitor. %s"}, + {IDS_MI_INIT_ERR_LLDBDEBUGGER, "LLDB Debugger. %s"}, + {IDS_MI_INIT_ERR_DRIVERMGR, "Driver manager. %s"}, + {IDS_MI_INIT_ERR_DRIVER, "Driver. %s"}, + {IDS_MI_INIT_ERR_OUTOFBANDHANDLER, "Out-of-band handler. %s "}, + {IDS_MI_INIT_ERR_DEBUGSESSIONINFO, "LLDB debug session info. %s "}, + {IDS_MI_INIT_ERR_THREADMANAGER, "Unable to init thread manager."}, + {IDS_MI_INIT_ERR_CLIENT_USING_DRIVER, "Initialising the client to this driver failed."}, + {IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION, "Initialising a local debug session failed."}, + {IDS_CODE_ERR_INVALID_PARAMETER_VALUE, "Code. Invalid parameter passed to function '%s'"}, + {IDS_CODE_ERR_INVALID_PARAM_NULL_POINTER, "Code. NULL pointer passes as a parameter to function '%s'"}, + {IDS_CODE_ERR_INVALID_ENUMERATION_VALUE, "Code. Invalid enumeration value encountered in function '%s'"}, + { + IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER, "LLDB Debugger. LLDB Listener is not valid", + }, + { + IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER, "LLDB Debugger. LLDB Debugger is not valid", + }, + {IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER, + "LLDB Debugger. CMIDriverBase derived driver needs to be set prior to CMICmnLLDBDDebugger initialisation"}, + {IDS_LLDBDEBUGGER_ERR_STARTLISTENER, "LLDB Debugger. Starting listening events for '%s' failed"}, + {IDS_LLDBDEBUGGER_ERR_THREADCREATIONFAIL, "LLDB Debugger. Thread creation failed '%s'"}, + {IDS_LLDBDEBUGGER_ERR_THREAD_DELETE, "LLDB Debugger. Thread failed to delete '%s'"}, + {IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER, "LLDB Debugger. Invalid SB broadcaster class name '%s' "}, + {IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME, "LLDB Debugger. Invalid client name '%s' "}, + {IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERD, "LLDB Debugger. Client name '%s' not registered for listening events"}, + {IDS_LLDBDEBUGGER_ERR_STOPLISTENER, "LLDB Debugger. Failure occurred stopping event for client '%s' SBBroadcaster '%s'"}, + {IDS_LLDBDEBUGGER_ERR_BROARDCASTER_NAME, "LLDB Debugger. Broardcaster's name '%s' is not valid"}, + {IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT, "LLDB Debugger. Unhandled event '%s'"}, + {IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT, "LLDB Out-of-band. Handling event for '%s', an event enumeration '%d' not recognised"}, + {IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID, "LLDB Out-of-band. Invalid '%s' in '%s'"}, + {IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND, "LLDB Out-of-band. %s. Breakpoint information for breakpoint ID %d not found"}, + {IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET, "LLDB Out-of-band. %s. Failed to retrieve breakpoint information for for breakpoint ID %d"}, + {IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET, "LLDB Out-of-band. %s. Failed to set breakpoint information for for breakpoint ID %d"}, + {IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE, "LLDB Out-of-band. %s. Failed to form the MI Out-of-band response"}, + {IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET, "LLDB Out-of-band. %s. Failed to retrieve frame information"}, + {IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE, + "LLDB Out-of-band. %s. Event handler tried to set new MI Driver running state and failed. %s"}, + {IDS_LLDBOUTOFBAND_ERR_BRKPT_CNT_EXCEEDED, + "LLDB Out-of-band. '%s'. Number of valid breakpoint exceeded %d. Cannot create new breakpoint with ID %d"}, + {IDS_DBGSESSION_ERR_SHARED_DATA_RELEASE, + "LLDB debug session info. Release some or all of the data shared across command instances failed"}, + {IDS_DBGSESSION_ERR_SHARED_DATA_ADD, "LLDB debug session info. Failed to add '%s' data to the shared data command container"}, + {IDS_MI_SHTDWN_ERR_LOG, "Log. Error occurred during shutdown. %s"}, + {IDS_MI_SHUTDOWN_ERR, "Server shutdown failure. %s"}, + {IDE_MI_SHTDWN_ERR_RESOURCES, "Resources. Error occurred during shutdown. %s"}, + {IDE_MI_SHTDWN_ERR_STREAMSTDIN, "Stdin. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, "Stdin handler. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_STREAMSTDOUT, "Stdout. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_STREAMSTDERR, "Stderr. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_THREADMGR, "Thread Mgr. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_CMDINTERPRETER, "Command interpreter. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_CMDMGR, "Command manager. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_CMDFACTORY, "Command factory. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_CMDMONITOR, "Command invoker. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_CMDINVOKER, "Command monitor. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_LLDBDEBUGGER, "LLDB Debugger. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_DRIVERMGR, "Driver manager. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_DRIVER, "Driver. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_OUTOFBANDHANDLER, "Out-of-band handler. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_DEBUGSESSIONINFO, "LLDB debug session info. Error occurred during shutdown. %s"}, + {IDE_MI_SHTDWN_ERR_THREADMANAGER, "Unable to shutdown thread manager"}, + {IDS_DRIVER_ERR_PARSE_ARGS, "Driver. Driver '%s'. Parse args error '%s'"}, + {IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN, "Driver. Driver '%s'. Parse args error unknown"}, + {IDS_DRIVER_ERR_CURRENT_NOT_SET, "Driver. Current working driver has not been set. Call CMIDriverMgr::SetUseThisDriverToDoWork()"}, + {IDS_DRIVER_ERR_NON_REGISTERED, "Driver. No suitable drivers registered with the CMIDriverMgr to do work"}, + {IDS_DRIVER_SAY_DRIVER_USING, "Driver. Using driver '%s' internally"}, + {IDS_DRIVER_ERR_ID_INVALID, "Driver. Driver '%s' invalid ID '%s'"}, + {IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR, "Driver. Fall through driver '%s' (ID:'%s') error '%s'"}, + {IDS_DRIVER_CMD_RECEIVED, "Driver. Received command '%s'. It was %shandled%s"}, + {IDS_DRIVER_CMD_NOT_IN_FACTORY, ". Command '%s' not in Command Factory"}, + { + IDS_DRIVER_ERR_DRIVER_STATE_ERROR, "Driver. Driver running state error. Cannot go to next state from present state as not allowed", + }, + {IDS_DRIVER_WAITING_STDIN_DATA, "Driver. Main thread suspended waiting on Stdin Monitor to resume main thread"}, + {IDS_DRIVER_ERR_MAINLOOP, "Driver. Error in do main loop. %s"}, + {IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL, "Driver. --executable argument given. Local debugging is not implemented."}, + {IDS_DRIVER_ERR_LOCAL_DEBUG_INIT, "Driver. --executable argument given. Initialising local debugging failed."}, + {IDS_STDOUT_ERR_NOT_ALL_DATA_WRITTEN, "Stdout. Not all data was written to stream. The data '%s'"}, + {IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN, "Stderr. Not all data was written to stream. The data '%s'"}, + {IDS_CMD_ARGS_ERR_N_OPTIONS_REQUIRED, "Command Args. Missing options, %d or more required"}, + {IDS_CMD_ARGS_ERR_OPTION_NOT_FOUND, "Command Args. Option '%s' not found"}, + {IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY, "Mandatory args not found: %s"}, + {IDS_CMD_ARGS_ERR_VALIDATION_INVALID, "Invalid args: %s"}, + {IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID, "Mandatory args not found: %s. Invalid args: %s"}, + {IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF, "Args missing additional information: %s"}, + {IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN, "Not all arguments or options were recognised: %s"}, + {IDS_CMD_ARGS_ERR_PREFIX_MSG, "Command Args. Validation failed. "}, + {IDS_VARIANT_ERR_USED_BASECLASS, "Variant container: Variant object used the base class. See CMIUtilVariant"}, + {IDS_VARIANT_ERR_MAP_KEY_INVALID, "Variant container: Invalid ID '%s'"}, + {IDS_WORD_INVALIDBRKTS, ""}, + {IDS_WORD_NONE, "None"}, + {IDS_WORD_NOT, "not"}, + {IDS_WORD_INVALIDEMPTY, ""}, + {IDS_WORD_INVALIDNULLPTR, ""}, + {IDS_WORD_UNKNOWNBRKTS, ""}, + {IDS_WORD_NOT_IMPLEMENTED, "Not implemented"}, + {IDS_WORD_NOT_IMPLEMENTED_BRKTS, ""}, + {IDS_WORD_UNKNOWNTYPE_BRKTS, ""}, + {IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS, ""}, + {IDS_CMD_ERR_N_OPTIONS_REQUIRED, "Command '%s'. Missing options, %d required"}, + {IDS_CMD_ERR_OPTION_NOT_FOUND, "Command '%s'. Option '%s' not found"}, + {IDS_CMD_ERR_ARGS, "Command '%s'. %s"}, + {IDS_CMD_WRN_ARGS_NOT_HANDLED, "Command '%s'. Warning the following options not handled by the command: %s"}, + {IDS_CMD_ERR_FNFAILED, "Command '%s'. Fn '%s' failed"}, + {IDS_CMD_ERR_SHARED_DATA_NOT_FOUND, "Command '%s'. Shared data '%s' not found"}, + {IDS_CMD_ERR_LLDBPROCESS_DETACH, "Command '%s'. Process detach failed. '%s'"}, + {IDS_CMD_ERR_SETWKDIR, "Command '%s'. Failed to set working directory '%s'"}, + {IDS_CMD_ERR_INVALID_TARGET, "Command '%s'. Target binary '%s' is invalid. %s"}, + {IDS_CMD_ERR_INVALID_TARGET_CURRENT, "Command '%s'. Current SBTarget is invalid"}, + {IDS_CMD_ERR_INVALID_TARGET_TYPE, "Command '%s'. Target type '%s' is not recognised"}, + {IDS_CMD_ERR_INVALID_TARGET_PLUGIN, "Command '%s'. Target plugin is invalid. %s"}, + {IDS_CMD_ERR_CONNECT_TO_TARGET, "Command '%s'. Error connecting to target: '%s'"}, + {IDS_CMD_ERR_INVALID_TARGETPLUGINCURRENT, "Command '%s'. Current target plugin is invalid"}, + {IDS_CMD_ERR_NOT_IMPLEMENTED, "Command '%s'. Command not implemented"}, + {IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED, "Command '%s'. Command not implemented as it has been deprecated"}, + {IDS_CMD_ERR_CREATE_TARGET, "Command '%s'. Create target failed: %s"}, + {IDS_CMD_ERR_BRKPT_LOCATION_FORMAT, "Command '%s'. Incorrect format for breakpoint location '%s'"}, + {IDS_CMD_ERR_BRKPT_INVALID, "Command '%s'. Breakpoint '%s' invalid"}, + {IDS_CMD_ERR_BRKPT_CNT_EXCEEDED, "Command '%s'. Number of valid breakpoint exceeded %d. Cannot create new breakpoint '%s'"}, + {IDS_CMD_ERR_SOME_ERROR, "Command '%s'. Error: %s"}, + {IDS_CMD_ERR_THREAD_INVALID, "Command '%s'. Thread ID invalid"}, + {IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID, "Command '%s'. Thread frame range invalid"}, + {IDS_CMD_ERR_FRAME_INVALID, "Command '%s'. Frame ID invalid"}, + {IDS_CMD_ERR_VARIABLE_DOESNOTEXIST, "Command '%s'. Variable '%s' does not exist"}, + {IDS_CMD_ERR_VARIABLE_ENUM_INVALID, "Command '%s'. Invalid enumeration for variable '%s' formatted string '%s'"}, + {IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH, "Command '%s'. Failed to get expression for variable '%s'"}, + {IDS_CMD_ERR_VARIABLE_CREATION_FAILED, "Failed to create variable object for '%s'"}, + {IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION, ""}, + {IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION, ""}, + {IDS_CMD_ERR_DISASM_ADDR_START_INVALID, "Command '%s'. Invalid start value '%s'"}, + {IDS_CMD_ERR_DISASM_ADDR_END_INVALID, "Command '%s'. Invalid end value '%s'"}, + {IDS_CMD_ERR_MEMORY_ALLOC_FAILURE, "Command '%s'. Failed to allocate memory %d bytes"}, + {IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK, "Command '%s'. LLDB unable to read entire memory block of %u bytes at address 0x%08x"}, + {IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES, "Command '%s'. Unable to read memory block of %u bytes at address 0x%08x: %s "}, + {IDS_CMD_ERR_INVALID_PROCESS, "Command '%s'. Invalid process during debug session"}, + {IDS_CMD_ERR_INVALID_FORMAT_TYPE, "Command '%s'. Invalid var format type '%s'"}, + {IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND, "Command '%s'. Breakpoint information for breakpoint ID %d not found"}, + {IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES, "Command '%s'. Unable to write memory block of %u bytes at address 0x%08x: %s "}, + {IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK, "Command '%s'. LLDB unable to write entire memory block of %u bytes at address 0x%08x"}, + {IDS_CMD_ERR_SET_NEW_DRIVER_STATE, "Command '%s'. Command tried to set new MI Driver running state and failed. %s"}, + {IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND, "The request '%s' was not recogised, not implemented"}, + {IDS_CMD_ERR_INFO_PRINTFN_FAILED, "The request '%s' failed."}, + {IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH, "'solib-search-path' requires at least one argument"}}; //++ ------------------------------------------------------------------------------------ -// Details: CMICmnResources constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnResources constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnResources::CMICmnResources( void ) -: m_nResourceId2TextDataSize( 0 ) +CMICmnResources::CMICmnResources(void) + : m_nResourceId2TextDataSize(0) { - // Do not use this constructor, use Initialize() + // Do not use this constructor, use Initialize() } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnResources destructor. -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnResources destructor. +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnResources::~CMICmnResources( void ) +CMICmnResources::~CMICmnResources(void) { - // Do not use this destructor, use Shutdown() + // Do not use this destructor, use Shutdown() } //++ ------------------------------------------------------------------------------------ -// Details: Initialize the resources and set locality for the server. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialize the resources and set locality for the server. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnResources::Initialize( void ) +bool +CMICmnResources::Initialize(void) { - m_clientUsageRefCnt++; + m_clientUsageRefCnt++; - if( m_bInitialized ) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - m_bInitialized = ReadResourceStringData(); + m_bInitialized = ReadResourceStringData(); - return m_bInitialized; + return m_bInitialized; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this object. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Release resources for *this object. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnResources::Shutdown( void ) +bool +CMICmnResources::Shutdown(void) { - if( --m_clientUsageRefCnt > 0 ) - return MIstatus::success; - - if( !m_bInitialized ) - return MIstatus::success; + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; + + if (!m_bInitialized) + return MIstatus::success; - // Tear down resource explicitly - m_mapRscrIdToTextData.clear(); + // Tear down resource explicitly + m_mapRscrIdToTextData.clear(); - m_bInitialized = false; + m_bInitialized = false; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Initialize the resources and set locality for the server. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialize the resources and set locality for the server. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnResources::ReadResourceStringData( void ) +bool +CMICmnResources::ReadResourceStringData(void) { - m_nResourceId2TextDataSize = sizeof ms_pResourceId2TextData / sizeof ms_pResourceId2TextData[ 0 ]; - for( MIuint i = 0; i < m_nResourceId2TextDataSize; i++ ) - { - const SRsrcTextData * pRscrData = &ms_pResourceId2TextData[ i ]; - MapPairRscrIdToTextData_t pr( pRscrData->id, pRscrData->pTextData ); - m_mapRscrIdToTextData.insert( pr ); - } - - return MIstatus::success; + m_nResourceId2TextDataSize = sizeof ms_pResourceId2TextData / sizeof ms_pResourceId2TextData[0]; + for (MIuint i = 0; i < m_nResourceId2TextDataSize; i++) + { + const SRsrcTextData *pRscrData = &ms_pResourceId2TextData[i]; + MapPairRscrIdToTextData_t pr(pRscrData->id, pRscrData->pTextData); + m_mapRscrIdToTextData.insert(pr); + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the corresponding text assigned to the resource ID. -// Type: Method. -// Args: vResourceId - (R) MI resource ID. -// Return: CMIUtilString - Resource text. -// Throws: None. +// Details: Retrieve the corresponding text assigned to the resource ID. +// Type: Method. +// Args: vResourceId - (R) MI resource ID. +// Return: CMIUtilString - Resource text. +// Throws: None. //-- -CMIUtilString CMICmnResources::GetString( const MIuint vResourceId ) const +CMIUtilString +CMICmnResources::GetString(const MIuint vResourceId) const { - CMIUtilString str; - const bool bFound = GetStringFromResource( vResourceId, str ); MIunused( bFound ); - assert( bFound ); + CMIUtilString str; + const bool bFound = GetStringFromResource(vResourceId, str); + MIunused(bFound); + assert(bFound); - return str; + return str; } //++ ------------------------------------------------------------------------------------ -// Details: Determine the MI resource ID existings. -// Type: Method. -// Args: vResourceId - (R) MI resource ID. -// Return: True - Exists. -// False - Not found. -// Throws: None. +// Details: Determine the MI resource ID existings. +// Type: Method. +// Args: vResourceId - (R) MI resource ID. +// Return: True - Exists. +// False - Not found. +// Throws: None. //-- -bool CMICmnResources::HasString( const MIuint vResourceId ) const +bool +CMICmnResources::HasString(const MIuint vResourceId) const { - CMIUtilString str; - return GetStringFromResource( vResourceId, str ); + CMIUtilString str; + return GetStringFromResource(vResourceId, str); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the resource text data for the given resource ID. If a resourse ID -// cannot be found and error is given returning the ID of the resource that -// cannot be located. -// Type: Method. -// Args: vResourceId - (R) MI resource ID. -// vrwResourceString - (W) Text. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieve the resource text data for the given resource ID. If a resourse ID +// cannot be found and error is given returning the ID of the resource that +// cannot be located. +// Type: Method. +// Args: vResourceId - (R) MI resource ID. +// vrwResourceString - (W) Text. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnResources::GetStringFromResource( const MIuint vResourceId, CMIUtilString & vrwResourceString ) const +bool +CMICmnResources::GetStringFromResource(const MIuint vResourceId, CMIUtilString &vrwResourceString) const { - MapRscrIdToTextData_t::const_iterator it = m_mapRscrIdToTextData.find( vResourceId ); - if( it == m_mapRscrIdToTextData.end() ) - { - // Check this is a static variable init that needs this before we are ready - if( !m_bInitialized ) - { - (const_cast< CMICmnResources * >( this ))->Initialize(); - it = m_mapRscrIdToTextData.find( vResourceId ); - if( it == m_mapRscrIdToTextData.end() ) - { - vrwResourceString = MIRSRC( IDS_RESOURCES_ERR_STRING_TABLE_INVALID ); - return MIstatus::failure; - } - } + MapRscrIdToTextData_t::const_iterator it = m_mapRscrIdToTextData.find(vResourceId); + if (it == m_mapRscrIdToTextData.end()) + { + // Check this is a static variable init that needs this before we are ready + if (!m_bInitialized) + { + (const_cast(this))->Initialize(); + it = m_mapRscrIdToTextData.find(vResourceId); + if (it == m_mapRscrIdToTextData.end()) + { + vrwResourceString = MIRSRC(IDS_RESOURCES_ERR_STRING_TABLE_INVALID); + return MIstatus::failure; + } + } - if( it == m_mapRscrIdToTextData.end() ) - { - vrwResourceString = CMIUtilString::Format( MIRSRC( IDS_RESOURCES_ERR_STRING_NOT_FOUND ), vResourceId ); - return MIstatus::failure; - } - } + if (it == m_mapRscrIdToTextData.end()) + { + vrwResourceString = CMIUtilString::Format(MIRSRC(IDS_RESOURCES_ERR_STRING_NOT_FOUND), vResourceId); + return MIstatus::failure; + } + } - const MIuint nRsrcId( (*it).first ); MIunused( nRsrcId ); - const MIchar * pRsrcData( (*it).second ); + const MIuint nRsrcId((*it).first); + MIunused(nRsrcId); + const MIchar *pRsrcData((*it).second); - // Return result - vrwResourceString = pRsrcData; + // Return result + vrwResourceString = pRsrcData; - return MIstatus::success; + return MIstatus::success; } - diff --git a/tools/lldb-mi/MICmnResources.h b/tools/lldb-mi/MICmnResources.h index f836f8d1b8aa..cd9208cfb7a4 100644 --- a/tools/lldb-mi/MICmnResources.h +++ b/tools/lldb-mi/MICmnResources.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnResources.h +// File: MICmnResources.h // -// Overview: CMICmnResources interface. +// Overview: CMICmnResources interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -26,326 +26,323 @@ // In-house headers: #include "MIUtilSingletonBase.h" -#include "MIUtilString.h" +#include "MIUtilString.h" #include "MICmnBase.h" //++ ============================================================================ // Details: MI string test data resource definitions. These IDs match up with -// actual string data in a map internal to CMICmnResources. -// *** Be sure to update ms_pResourceId2TextData[] array **** +// actual string data in a map internal to CMICmnResources. +// *** Be sure to update ms_pResourceId2TextData[] array **** enum { - IDS_PROJNAME = 1, - IDS_MI_VERSION_DESCRIPTION_DEBUG , - IDS_MI_VERSION_DESCRIPTION , - IDS_MI_APPNAME_SHORT , - IDS_MI_APPNAME_LONG , - IDS_MI_APP_FILEPATHNAME , - IDS_MI_APP_ARGS , - IDE_MI_VERSION_GDB , - - IDS_UTIL_FILE_ERR_INVALID_PATHNAME , - IDS_UTIL_FILE_ERR_OPENING_FILE , - IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN , - IDE_UTIL_FILE_ERR_WRITING_FILE , - IDE_UTIL_FILE_ERR_WRITING_NOTOPEN , - - IDS_RESOURCES_ERR_STRING_NOT_FOUND , - IDS_RESOURCES_ERR_STRING_TABLE_INVALID , - - IDS_MI_CLIENT_MSG , - - IDS_LOG_MSG_CREATION_DATE , - IDS_LOG_MSG_FILE_LOGGER_PATH , - IDS_LOG_MSG_VERSION , - IDS_LOG_ERR_FILE_LOGGER_DISABLED , - IDS_LOG_MEDIUM_ERR_INIT , - IDS_LOG_MEDIUM_ERR_WRITE_ANY , - IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL , - IDE_MEDIUMFILE_ERR_GET_FILE_PATHNAME_SYS, - - IDS_MEDIUMFILE_NAME , - IDS_MEDIUMFILE_ERR_INVALID_PATH , - IDS_MEDIUMFILE_ERR_FILE_HEADER , - IDS_MEDIUMFILE_NAME_LOG , - - IDE_OS_ERR_UNKNOWN , - IDE_OS_ERR_RETRIEVING , - - IDS_DRIVERMGR_DRIVER_ERR_INIT , - - IDE_MEDIUMSTDERR_NAME , - IDE_MEDIUMSTDOUT_NAME , - - IDE_MI_APP_EXIT_OK , - IDE_MI_APP_EXIT_WITH_PROBLEM , - IDE_MI_APP_EXIT_WITH_PROBLEM_NO_LOG , - - IDE_MI_APP_DESCRIPTION , - IDE_MI_APP_INFORMATION , - IDE_MI_APP_ARG_USAGE , - IDE_MI_APP_ARG_HELP , - IDE_MI_APP_ARG_VERSION , - IDE_MI_APP_ARG_VERSION_LONG , - IDE_MI_APP_ARG_INTERPRETER , - IDE_MI_APP_ARG_EXECUTEABLE , - IDE_MI_APP_ARG_NO_APP_LOG , - IDE_MI_APP_ARG_EXAMPLE , - IDE_MI_APP_ARG_EXECUTABLE , - - IDS_STDIN_ERR_INVALID_PROMPT , - IDS_STDIN_ERR_THREAD_CREATION_FAILED , - IDS_STDIN_ERR_THREAD_DELETE , - IDS_STDIN_ERR_CHKING_BYTE_AVAILABLE , - IDS_STDIN_INPUT_CTRL_CHARS , - - IDS_CMD_QUIT_HELP , - - IDS_THREADMGR_ERR_THREAD_ID_INVALID , - IDS_THREADMGR_ERR_THREAD_FAIL_CREATE , - IDS_THREADMGR_ERR_THREAD_ID_NOT_FOUND , - IDS_THREADMGR_ERR_THREAD_STILL_ALIVE , - - IDS_FALLTHRU_DRIVER_CMD_RECEIVED , - - IDS_CMDFACTORY_ERR_INVALID_CMD_NAME , - IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN , - IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED , - IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED , - - IDS_CMDMGR_ERR_CMD_FAILED_CREATE , - IDS_CMDMGR_ERR_CMD_INVOKER , - - IDS_PROCESS_SIGNAL_RECEIVED , - - IDS_MI_INIT_ERR_LOG , - IDS_MI_INIT_ERR_RESOURCES , - IDS_MI_INIT_ERR_INIT , - IDS_MI_INIT_ERR_STREAMSTDIN , - IDS_MI_INIT_ERR_STREAMSTDIN_OSHANDLER , - IDS_MI_INIT_ERR_OS_STDIN_HANDLER , - IDS_MI_INIT_ERR_STREAMSTDOUT , - IDS_MI_INIT_ERR_STREAMSTDERR , - IDS_MI_INIT_ERR_FALLTHRUDRIVER , - IDS_MI_INIT_ERR_THREADMGR , - IDS_MI_INIT_ERR_CMDINTERPRETER , - IDS_MI_INIT_ERR_CMDMGR , - IDS_MI_INIT_ERR_CMDFACTORY , - IDS_MI_INIT_ERR_CMDINVOKER , - IDS_MI_INIT_ERR_CMDMONITOR , - IDS_MI_INIT_ERR_LLDBDEBUGGER , - IDS_MI_INIT_ERR_DRIVERMGR , - IDS_MI_INIT_ERR_DRIVER , - IDS_MI_INIT_ERR_OUTOFBANDHANDLER , - IDS_MI_INIT_ERR_DEBUGSESSIONINFO , - IDS_MI_INIT_ERR_THREADMANAGER , - IDS_MI_INIT_ERR_CLIENT_USING_DRIVER , - IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION , - - IDS_CODE_ERR_INVALID_PARAMETER_VALUE , - IDS_CODE_ERR_INVALID_PARAM_NULL_POINTER , - IDS_CODE_ERR_INVALID_ENUMERATION_VALUE , - - IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER , - IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER , - IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER , - IDS_LLDBDEBUGGER_ERR_STARTLISTENER , - IDS_LLDBDEBUGGER_ERR_THREADCREATIONFAIL , - IDS_LLDBDEBUGGER_ERR_THREAD_DELETE , - IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER , - IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME , - IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERD , - IDS_LLDBDEBUGGER_ERR_STOPLISTENER , - IDS_LLDBDEBUGGER_ERR_BROARDCASTER_NAME , - IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT , - - IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT , - IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID , - IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND , - IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET , - IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET , - IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE , - IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET , - IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE , - IDS_LLDBOUTOFBAND_ERR_BRKPT_CNT_EXCEEDED, - - - IDS_DBGSESSION_ERR_SHARED_DATA_RELEASE , - IDS_DBGSESSION_ERR_SHARED_DATA_ADD , - - IDS_MI_SHTDWN_ERR_LOG , - IDS_MI_SHUTDOWN_ERR , - IDE_MI_SHTDWN_ERR_RESOURCES , - IDE_MI_SHTDWN_ERR_STREAMSTDIN , - IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER , - IDS_MI_SHTDWN_ERR_STREAMSTDOUT , - IDS_MI_SHTDWN_ERR_STREAMSTDERR , - IDS_MI_SHTDWN_ERR_THREADMGR , - IDS_MI_SHTDWN_ERR_CMDINTERPRETER , - IDS_MI_SHTDWN_ERR_CMDMGR , - IDS_MI_SHTDWN_ERR_CMDFACTORY , - IDS_MI_SHTDWN_ERR_CMDINVOKER , - IDS_MI_SHTDWN_ERR_CMDMONITOR , - IDS_MI_SHTDWN_ERR_LLDBDEBUGGER , - IDS_MI_SHTDWN_ERR_DRIVERMGR , - IDS_MI_SHTDWN_ERR_DRIVER , - IDS_MI_SHTDWN_ERR_OUTOFBANDHANDLER , - IDS_MI_SHTDWN_ERR_DEBUGSESSIONINFO , - IDE_MI_SHTDWN_ERR_THREADMANAGER , - - IDS_DRIVER_ERR_PARSE_ARGS , - IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN , - IDS_DRIVER_ERR_CURRENT_NOT_SET , - IDS_DRIVER_ERR_NON_REGISTERED , - IDS_DRIVER_SAY_DRIVER_USING , - IDS_DRIVER_ERR_ID_INVALID , - IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR , - IDS_DRIVER_CMD_RECEIVED , - IDS_DRIVER_CMD_NOT_IN_FACTORY , - IDS_DRIVER_ERR_DRIVER_STATE_ERROR , - IDS_DRIVER_ERR_MAINLOOP , - IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL , - IDS_DRIVER_ERR_LOCAL_DEBUG_INIT , - - IDS_DRIVER_WAITING_STDIN_DATA , - - IDS_STDOUT_ERR_NOT_ALL_DATA_WRITTEN , - IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN , - - IDS_CMD_ARGS_ERR_N_OPTIONS_REQUIRED , - IDS_CMD_ARGS_ERR_OPTION_NOT_FOUND , - IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY , - IDS_CMD_ARGS_ERR_VALIDATION_INVALID , - IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID , - IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF , - IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN , - IDS_CMD_ARGS_ERR_PREFIX_MSG , - - IDS_VARIANT_ERR_USED_BASECLASS , - IDS_VARIANT_ERR_MAP_KEY_INVALID, - - IDS_WORD_INVALIDBRKTS , - IDS_WORD_NONE , - IDS_WORD_NOT , - IDS_WORD_INVALIDEMPTY , - IDS_WORD_INVALIDNULLPTR , - IDS_WORD_UNKNOWNBRKTS , - IDS_WORD_NOT_IMPLEMENTED , - IDS_WORD_NOT_IMPLEMENTED_BRKTS , - IDS_WORD_UNKNOWNTYPE_BRKTS , - IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS , - - IDS_CMD_ERR_N_OPTIONS_REQUIRED , - IDS_CMD_ERR_OPTION_NOT_FOUND , - IDS_CMD_ERR_ARGS , - IDS_CMD_WRN_ARGS_NOT_HANDLED , - IDS_CMD_ERR_FNFAILED , - IDS_CMD_ERR_SHARED_DATA_NOT_FOUND , - IDS_CMD_ERR_LLDBPROCESS_DETACH , - IDS_CMD_ERR_SETWKDIR , - IDS_CMD_ERR_INVALID_TARGET , - IDS_CMD_ERR_INVALID_TARGET_CURRENT , - IDS_CMD_ERR_INVALID_TARGET_TYPE , - IDS_CMD_ERR_INVALID_TARGET_PLUGIN , - IDS_CMD_ERR_CONNECT_TO_TARGET , - IDS_CMD_ERR_INVALID_TARGETPLUGINCURRENT , - IDS_CMD_ERR_NOT_IMPLEMENTED , - IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED , - IDS_CMD_ERR_CREATE_TARGET , - IDS_CMD_ERR_BRKPT_LOCATION_FORMAT , - IDS_CMD_ERR_BRKPT_INVALID , - IDS_CMD_ERR_BRKPT_CNT_EXCEEDED , - IDS_CMD_ERR_SOME_ERROR , - IDS_CMD_ERR_THREAD_INVALID , - IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID , - IDS_CMD_ERR_FRAME_INVALID , - IDS_CMD_ERR_VARIABLE_DOESNOTEXIST , - IDS_CMD_ERR_VARIABLE_ENUM_INVALID , - IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH , - IDS_CMD_ERR_VARIABLE_CREATION_FAILED , - IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION , - IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION , - IDS_CMD_ERR_DISASM_ADDR_START_INVALID , - IDS_CMD_ERR_DISASM_ADDR_END_INVALID , - IDS_CMD_ERR_MEMORY_ALLOC_FAILURE , - IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK , - IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES , - IDS_CMD_ERR_INVALID_PROCESS , - IDS_CMD_ERR_INVALID_FORMAT_TYPE , - IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND , - IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES , - IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK , - IDS_CMD_ERR_SET_NEW_DRIVER_STATE , - IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND , - IDS_CMD_ERR_INFO_PRINTFN_FAILED , - IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH + IDS_PROJNAME = 1, + IDS_MI_VERSION_DESCRIPTION_DEBUG, + IDS_MI_VERSION_DESCRIPTION, + IDS_MI_APPNAME_SHORT, + IDS_MI_APPNAME_LONG, + IDS_MI_APP_FILEPATHNAME, + IDS_MI_APP_ARGS, + IDE_MI_VERSION_GDB, + + IDS_UTIL_FILE_ERR_INVALID_PATHNAME, + IDS_UTIL_FILE_ERR_OPENING_FILE, + IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN, + IDE_UTIL_FILE_ERR_WRITING_FILE, + IDE_UTIL_FILE_ERR_WRITING_NOTOPEN, + + IDS_RESOURCES_ERR_STRING_NOT_FOUND, + IDS_RESOURCES_ERR_STRING_TABLE_INVALID, + + IDS_MI_CLIENT_MSG, + + IDS_LOG_MSG_CREATION_DATE, + IDS_LOG_MSG_FILE_LOGGER_PATH, + IDS_LOG_MSG_VERSION, + IDS_LOG_ERR_FILE_LOGGER_DISABLED, + IDS_LOG_MEDIUM_ERR_INIT, + IDS_LOG_MEDIUM_ERR_WRITE_ANY, + IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL, + IDE_MEDIUMFILE_ERR_GET_FILE_PATHNAME_SYS, + + IDS_MEDIUMFILE_NAME, + IDS_MEDIUMFILE_ERR_INVALID_PATH, + IDS_MEDIUMFILE_ERR_FILE_HEADER, + IDS_MEDIUMFILE_NAME_LOG, + + IDE_OS_ERR_UNKNOWN, + IDE_OS_ERR_RETRIEVING, + + IDS_DRIVERMGR_DRIVER_ERR_INIT, + + IDE_MEDIUMSTDERR_NAME, + IDE_MEDIUMSTDOUT_NAME, + + IDE_MI_APP_EXIT_OK, + IDE_MI_APP_EXIT_WITH_PROBLEM, + IDE_MI_APP_EXIT_WITH_PROBLEM_NO_LOG, + + IDE_MI_APP_DESCRIPTION, + IDE_MI_APP_INFORMATION, + IDE_MI_APP_ARG_USAGE, + IDE_MI_APP_ARG_HELP, + IDE_MI_APP_ARG_VERSION, + IDE_MI_APP_ARG_VERSION_LONG, + IDE_MI_APP_ARG_INTERPRETER, + IDE_MI_APP_ARG_EXECUTEABLE, + IDE_MI_APP_ARG_NO_APP_LOG, + IDE_MI_APP_ARG_EXAMPLE, + IDE_MI_APP_ARG_EXECUTABLE, + + IDS_STDIN_ERR_INVALID_PROMPT, + IDS_STDIN_ERR_THREAD_CREATION_FAILED, + IDS_STDIN_ERR_THREAD_DELETE, + IDS_STDIN_ERR_CHKING_BYTE_AVAILABLE, + IDS_STDIN_INPUT_CTRL_CHARS, + + IDS_CMD_QUIT_HELP, + + IDS_THREADMGR_ERR_THREAD_ID_INVALID, + IDS_THREADMGR_ERR_THREAD_FAIL_CREATE, + IDS_THREADMGR_ERR_THREAD_ID_NOT_FOUND, + IDS_THREADMGR_ERR_THREAD_STILL_ALIVE, + + IDS_FALLTHRU_DRIVER_CMD_RECEIVED, + + IDS_CMDFACTORY_ERR_INVALID_CMD_NAME, + IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN, + IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED, + IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED, + + IDS_CMDMGR_ERR_CMD_FAILED_CREATE, + IDS_CMDMGR_ERR_CMD_INVOKER, + + IDS_PROCESS_SIGNAL_RECEIVED, + + IDS_MI_INIT_ERR_LOG, + IDS_MI_INIT_ERR_RESOURCES, + IDS_MI_INIT_ERR_INIT, + IDS_MI_INIT_ERR_STREAMSTDIN, + IDS_MI_INIT_ERR_STREAMSTDIN_OSHANDLER, + IDS_MI_INIT_ERR_OS_STDIN_HANDLER, + IDS_MI_INIT_ERR_STREAMSTDOUT, + IDS_MI_INIT_ERR_STREAMSTDERR, + IDS_MI_INIT_ERR_FALLTHRUDRIVER, + IDS_MI_INIT_ERR_THREADMGR, + IDS_MI_INIT_ERR_CMDINTERPRETER, + IDS_MI_INIT_ERR_CMDMGR, + IDS_MI_INIT_ERR_CMDFACTORY, + IDS_MI_INIT_ERR_CMDINVOKER, + IDS_MI_INIT_ERR_CMDMONITOR, + IDS_MI_INIT_ERR_LLDBDEBUGGER, + IDS_MI_INIT_ERR_DRIVERMGR, + IDS_MI_INIT_ERR_DRIVER, + IDS_MI_INIT_ERR_OUTOFBANDHANDLER, + IDS_MI_INIT_ERR_DEBUGSESSIONINFO, + IDS_MI_INIT_ERR_THREADMANAGER, + IDS_MI_INIT_ERR_CLIENT_USING_DRIVER, + IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION, + + IDS_CODE_ERR_INVALID_PARAMETER_VALUE, + IDS_CODE_ERR_INVALID_PARAM_NULL_POINTER, + IDS_CODE_ERR_INVALID_ENUMERATION_VALUE, + + IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER, + IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER, + IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER, + IDS_LLDBDEBUGGER_ERR_STARTLISTENER, + IDS_LLDBDEBUGGER_ERR_THREADCREATIONFAIL, + IDS_LLDBDEBUGGER_ERR_THREAD_DELETE, + IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER, + IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME, + IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERD, + IDS_LLDBDEBUGGER_ERR_STOPLISTENER, + IDS_LLDBDEBUGGER_ERR_BROARDCASTER_NAME, + IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT, + + IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT, + IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID, + IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND, + IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET, + IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET, + IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE, + IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET, + IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE, + IDS_LLDBOUTOFBAND_ERR_BRKPT_CNT_EXCEEDED, + + IDS_DBGSESSION_ERR_SHARED_DATA_RELEASE, + IDS_DBGSESSION_ERR_SHARED_DATA_ADD, + + IDS_MI_SHTDWN_ERR_LOG, + IDS_MI_SHUTDOWN_ERR, + IDE_MI_SHTDWN_ERR_RESOURCES, + IDE_MI_SHTDWN_ERR_STREAMSTDIN, + IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, + IDS_MI_SHTDWN_ERR_STREAMSTDOUT, + IDS_MI_SHTDWN_ERR_STREAMSTDERR, + IDS_MI_SHTDWN_ERR_THREADMGR, + IDS_MI_SHTDWN_ERR_CMDINTERPRETER, + IDS_MI_SHTDWN_ERR_CMDMGR, + IDS_MI_SHTDWN_ERR_CMDFACTORY, + IDS_MI_SHTDWN_ERR_CMDINVOKER, + IDS_MI_SHTDWN_ERR_CMDMONITOR, + IDS_MI_SHTDWN_ERR_LLDBDEBUGGER, + IDS_MI_SHTDWN_ERR_DRIVERMGR, + IDS_MI_SHTDWN_ERR_DRIVER, + IDS_MI_SHTDWN_ERR_OUTOFBANDHANDLER, + IDS_MI_SHTDWN_ERR_DEBUGSESSIONINFO, + IDE_MI_SHTDWN_ERR_THREADMANAGER, + + IDS_DRIVER_ERR_PARSE_ARGS, + IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN, + IDS_DRIVER_ERR_CURRENT_NOT_SET, + IDS_DRIVER_ERR_NON_REGISTERED, + IDS_DRIVER_SAY_DRIVER_USING, + IDS_DRIVER_ERR_ID_INVALID, + IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR, + IDS_DRIVER_CMD_RECEIVED, + IDS_DRIVER_CMD_NOT_IN_FACTORY, + IDS_DRIVER_ERR_DRIVER_STATE_ERROR, + IDS_DRIVER_ERR_MAINLOOP, + IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL, + IDS_DRIVER_ERR_LOCAL_DEBUG_INIT, + + IDS_DRIVER_WAITING_STDIN_DATA, + + IDS_STDOUT_ERR_NOT_ALL_DATA_WRITTEN, + IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN, + + IDS_CMD_ARGS_ERR_N_OPTIONS_REQUIRED, + IDS_CMD_ARGS_ERR_OPTION_NOT_FOUND, + IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY, + IDS_CMD_ARGS_ERR_VALIDATION_INVALID, + IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID, + IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF, + IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN, + IDS_CMD_ARGS_ERR_PREFIX_MSG, + + IDS_VARIANT_ERR_USED_BASECLASS, + IDS_VARIANT_ERR_MAP_KEY_INVALID, + + IDS_WORD_INVALIDBRKTS, + IDS_WORD_NONE, + IDS_WORD_NOT, + IDS_WORD_INVALIDEMPTY, + IDS_WORD_INVALIDNULLPTR, + IDS_WORD_UNKNOWNBRKTS, + IDS_WORD_NOT_IMPLEMENTED, + IDS_WORD_NOT_IMPLEMENTED_BRKTS, + IDS_WORD_UNKNOWNTYPE_BRKTS, + IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS, + + IDS_CMD_ERR_N_OPTIONS_REQUIRED, + IDS_CMD_ERR_OPTION_NOT_FOUND, + IDS_CMD_ERR_ARGS, + IDS_CMD_WRN_ARGS_NOT_HANDLED, + IDS_CMD_ERR_FNFAILED, + IDS_CMD_ERR_SHARED_DATA_NOT_FOUND, + IDS_CMD_ERR_LLDBPROCESS_DETACH, + IDS_CMD_ERR_SETWKDIR, + IDS_CMD_ERR_INVALID_TARGET, + IDS_CMD_ERR_INVALID_TARGET_CURRENT, + IDS_CMD_ERR_INVALID_TARGET_TYPE, + IDS_CMD_ERR_INVALID_TARGET_PLUGIN, + IDS_CMD_ERR_CONNECT_TO_TARGET, + IDS_CMD_ERR_INVALID_TARGETPLUGINCURRENT, + IDS_CMD_ERR_NOT_IMPLEMENTED, + IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED, + IDS_CMD_ERR_CREATE_TARGET, + IDS_CMD_ERR_BRKPT_LOCATION_FORMAT, + IDS_CMD_ERR_BRKPT_INVALID, + IDS_CMD_ERR_BRKPT_CNT_EXCEEDED, + IDS_CMD_ERR_SOME_ERROR, + IDS_CMD_ERR_THREAD_INVALID, + IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID, + IDS_CMD_ERR_FRAME_INVALID, + IDS_CMD_ERR_VARIABLE_DOESNOTEXIST, + IDS_CMD_ERR_VARIABLE_ENUM_INVALID, + IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH, + IDS_CMD_ERR_VARIABLE_CREATION_FAILED, + IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION, + IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION, + IDS_CMD_ERR_DISASM_ADDR_START_INVALID, + IDS_CMD_ERR_DISASM_ADDR_END_INVALID, + IDS_CMD_ERR_MEMORY_ALLOC_FAILURE, + IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK, + IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES, + IDS_CMD_ERR_INVALID_PROCESS, + IDS_CMD_ERR_INVALID_FORMAT_TYPE, + IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND, + IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES, + IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK, + IDS_CMD_ERR_SET_NEW_DRIVER_STATE, + IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND, + IDS_CMD_ERR_INFO_PRINTFN_FAILED, + IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH }; //++ ============================================================================ -// Details: MI common code implementation class. Handle application resources -// and locality. -// Singleton class. -// Gotchas: None. -// Authors: Illya Rudkin 29/01/2014. -// Changes: None. +// Details: MI common code implementation class. Handle application resources +// and locality. +// Singleton class. +// Gotchas: None. +// Authors: Illya Rudkin 29/01/2014. +// Changes: None. //-- -class CMICmnResources -: public CMICmnBase -, public MI::ISingleton< CMICmnResources > +class CMICmnResources : public CMICmnBase, public MI::ISingleton { - friend class MI::ISingleton< CMICmnResources >; - -// Methods: -public: - bool Initialize( void ); - bool Shutdown( void ); - - CMIUtilString GetString( const MIuint vResourceId ) const; - bool HasString( const MIuint vResourceId ) const; - -// Typedef: -private: - typedef std::map< MIuint, const MIchar * > MapRscrIdToTextData_t; - typedef std::pair< MIuint, const MIchar * > MapPairRscrIdToTextData_t; - -// Enumerations: -private: - enum Buffer_e - { - eBufferSize = 2048 - }; - -// Structs: -private: - struct SRsrcTextData - { - MIuint id; - const MIchar * pTextData; - }; - -// Methods: -private: - /* ctor */ CMICmnResources( void ); - /* ctor */ CMICmnResources( const CMICmnResources & ); - void operator=( const CMICmnResources & ); - - bool GetStringFromResource( const MIuint vResourceId, CMIUtilString & vrwResourceString ) const; - bool ReadResourceStringData( void ); - -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMICmnResources( void ); - -// Attributes: -private: - static const SRsrcTextData ms_pResourceId2TextData[]; - // - MIuint m_nResourceId2TextDataSize; - MapRscrIdToTextData_t m_mapRscrIdToTextData; + friend class MI::ISingleton; + + // Methods: + public: + bool Initialize(void); + bool Shutdown(void); + + CMIUtilString GetString(const MIuint vResourceId) const; + bool HasString(const MIuint vResourceId) const; + + // Typedef: + private: + typedef std::map MapRscrIdToTextData_t; + typedef std::pair MapPairRscrIdToTextData_t; + + // Enumerations: + private: + enum Buffer_e + { + eBufferSize = 2048 + }; + + // Structs: + private: + struct SRsrcTextData + { + MIuint id; + const MIchar *pTextData; + }; + + // Methods: + private: + /* ctor */ CMICmnResources(void); + /* ctor */ CMICmnResources(const CMICmnResources &); + void operator=(const CMICmnResources &); + + bool GetStringFromResource(const MIuint vResourceId, CMIUtilString &vrwResourceString) const; + bool ReadResourceStringData(void); + + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMICmnResources(void); + + // Attributes: + private: + static const SRsrcTextData ms_pResourceId2TextData[]; + // + MIuint m_nResourceId2TextDataSize; + MapRscrIdToTextData_t m_mapRscrIdToTextData; }; //++ ========================================================================= // Details: Macro short cut for retrieving a text data resource //-- -#define MIRSRC( x ) CMICmnResources::Instance().GetString( x ).c_str() +#define MIRSRC(x) CMICmnResources::Instance().GetString(x).c_str() diff --git a/tools/lldb-mi/MICmnStreamStderr.cpp b/tools/lldb-mi/MICmnStreamStderr.cpp index 1d66110eab07..cd09e8fc33d0 100644 --- a/tools/lldb-mi/MICmnStreamStderr.cpp +++ b/tools/lldb-mi/MICmnStreamStderr.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnStreamStderr.cpp +// File: MICmnStreamStderr.cpp // -// Overview: CMICmnStreamStderr implementation. +// Overview: CMICmnStreamStderr implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -26,232 +26,240 @@ #include "MIDriver.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStderr constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnStreamStderr constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnStreamStderr::CMICmnStreamStderr( void ) +CMICmnStreamStderr::CMICmnStreamStderr(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStderr destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnStreamStderr destructor. +// Type: Overridable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnStreamStderr::~CMICmnStreamStderr( void ) +CMICmnStreamStderr::~CMICmnStreamStderr(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this stderr stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialize resources for *this stderr stream. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStderr::Initialize( void ) +bool +CMICmnStreamStderr::Initialize(void) { - m_clientUsageRefCnt++; + m_clientUsageRefCnt++; - if( m_bInitialized ) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; + + bool bOk = MIstatus::success; - bool bOk = MIstatus::success; - #ifdef _MSC_VER - // Debugging / I/O issues with client. - // This is only required on Windows if you do not use ::flush(stderr). MI uses - // ::flush(stderr) - // It trys to ensure the process attached to the stderr steam gets ALL the data. - //::setbuf( stderr, NULL ); +// Debugging / I/O issues with client. +// This is only required on Windows if you do not use ::flush(stderr). MI uses +// ::flush(stderr) +// It trys to ensure the process attached to the stderr steam gets ALL the data. +//::setbuf( stderr, NULL ); #endif // _MSC_VER - - m_bInitialized = bOk; - return MIstatus::success; + m_bInitialized = bOk; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this stderr stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Release resources for *this stderr stream. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStderr::Shutdown( void ) +bool +CMICmnStreamStderr::Shutdown(void) { - if( --m_clientUsageRefCnt > 0 ) - return MIstatus::success; - - if( !m_bInitialized ) - return MIstatus::success; + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; + + if (!m_bInitialized) + return MIstatus::success; - ClrErrorDescription(); + ClrErrorDescription(); - m_bInitialized = false; + m_bInitialized = false; - return MIstatus::success; -} + return MIstatus::success; +} //++ ------------------------------------------------------------------------------------ -// Details: Write text data to stderr. Prefix the message with "MI:". The text data does -// not need to include a carrage line return as this is added to the text. The -// function also then passes the text data into the CMICmnLog logger. -// Type: Method. -// Args: vText - (R) Text data. -// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Write text data to stderr. Prefix the message with "MI:". The text data does +// not need to include a carrage line return as this is added to the text. The +// function also then passes the text data into the CMICmnLog logger. +// Type: Method. +// Args: vText - (R) Text data. +// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStderr::Write( const CMIUtilString & vText, const bool vbSendToLog /* = true */ ) +bool +CMICmnStreamStderr::Write(const CMIUtilString &vText, const bool vbSendToLog /* = true */) { - if( vText.length() == 0 ) - return MIstatus::failure; + if (vText.length() == 0) + return MIstatus::failure; - const CMIUtilString strPrefixed( CMIUtilString::Format( "%s: %s", CMIDriver::Instance().GetAppNameShort().c_str(), vText.c_str() ) ); + const CMIUtilString strPrefixed(CMIUtilString::Format("%s: %s", CMIDriver::Instance().GetAppNameShort().c_str(), vText.c_str())); - return WritePriv( strPrefixed, vText, vbSendToLog ); + return WritePriv(strPrefixed, vText, vbSendToLog); } //++ ------------------------------------------------------------------------------------ -// Details: Write an LLDB text message to stderr. -// The text data does not need to include a carrage line return as this is added -// to the text. The function also then passes the text data into the CMICmnLog -// logger. -// Type: Method. -// Args: vText - (R) Text data. -// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Write an LLDB text message to stderr. +// The text data does not need to include a carrage line return as this is added +// to the text. The function also then passes the text data into the CMICmnLog +// logger. +// Type: Method. +// Args: vText - (R) Text data. +// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStderr::WriteLLDBMsg( const CMIUtilString & vText, const bool vbSendToLog /* = true */ ) +bool +CMICmnStreamStderr::WriteLLDBMsg(const CMIUtilString &vText, const bool vbSendToLog /* = true */) { - if( vText.length() == 0 ) - return MIstatus::failure; + if (vText.length() == 0) + return MIstatus::failure; - const CMIUtilString strPrefixed( CMIUtilString::Format( "LLDB: %s", vText.c_str() ) ); + const CMIUtilString strPrefixed(CMIUtilString::Format("LLDB: %s", vText.c_str())); - return WritePriv( vText, strPrefixed, vbSendToLog ); + return WritePriv(vText, strPrefixed, vbSendToLog); } //++ ------------------------------------------------------------------------------------ -// Details: Write text data to stderr. The text data does not need to -// include a carrage line return as this is added to the text. The function also -// then passes the text data into the CMICmnLog logger. -// Type: Method. -// Args: vText - (R) Text data. May be prefixed with MI app's short name. -// vTxtForLogFile - (R) Text data. -// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Write text data to stderr. The text data does not need to +// include a carrage line return as this is added to the text. The function also +// then passes the text data into the CMICmnLog logger. +// Type: Method. +// Args: vText - (R) Text data. May be prefixed with MI app's short name. +// vTxtForLogFile - (R) Text data. +// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStderr::WritePriv( const CMIUtilString & vText, const CMIUtilString & vTxtForLogFile, const bool vbSendToLog /* = true */ ) +bool +CMICmnStreamStderr::WritePriv(const CMIUtilString &vText, const CMIUtilString &vTxtForLogFile, const bool vbSendToLog /* = true */) { - if( vText.length() == 0 ) - return MIstatus::failure; - - bool bOk = MIstatus::success; - { - // Grab the stderr thread lock while we print - CMIUtilThreadLock _lock( m_mutex ); - - // Send this text to stderr - const MIuint status = ::fputs( vText.c_str(), stderr ); - if( status == EOF ) - { - const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN ), vText.c_str() ) ); - SetErrorDescription( errMsg ); - bOk = MIstatus::failure; - } - else - { - ::fprintf( stderr, "\n" ); - ::fflush( stderr ); - } - - // Send this text to the log - if( bOk && vbSendToLog ) - bOk &= m_pLog->WriteLog( vTxtForLogFile ); - } - - return bOk; + if (vText.length() == 0) + return MIstatus::failure; + + bool bOk = MIstatus::success; + { + // Grab the stderr thread lock while we print + CMIUtilThreadLock _lock(m_mutex); + + // Send this text to stderr + const MIint status = ::fputs(vText.c_str(), stderr); + if (status == EOF) + { + const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN), vText.c_str())); + SetErrorDescription(errMsg); + bOk = MIstatus::failure; + } + else + { + ::fprintf(stderr, "\n"); + ::fflush(stderr); + } + + // Send this text to the log + if (bOk && vbSendToLog) + bOk &= m_pLog->WriteLog(vTxtForLogFile); + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Lock the availability of the stream stderr. Other users of *this stream will -// be stalled until it is available (Unlock()). -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Lock the availability of the stream stderr. Other users of *this stream will +// be stalled until it is available (Unlock()). +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStderr::Lock( void ) +bool +CMICmnStreamStderr::Lock(void) { - m_mutex.Lock(); - return MIstatus::success; + m_mutex.Lock(); + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Release a previously locked stderr. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Release a previously locked stderr. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStderr::Unlock( void ) +bool +CMICmnStreamStderr::Unlock(void) { - m_mutex.Unlock(); - return MIstatus::success; + m_mutex.Unlock(); + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Take MI Driver text message and send to the stderr stream. Also output to the -// MI Log file. -// Type: Static method. -// Args: vrTxt - (R) Text. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Take MI Driver text message and send to the stderr stream. Also output to the +// MI Log file. +// Type: Static method. +// Args: vrTxt - (R) Text. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnStreamStderr::TextToStderr( const CMIUtilString & vrTxt ) +bool +CMICmnStreamStderr::TextToStderr(const CMIUtilString &vrTxt) { - const bool bLock = CMICmnStreamStderr::Instance().Lock(); - const bool bOk = bLock && CMICmnStreamStderr::Instance().Write( vrTxt ); - bLock && CMICmnStreamStderr::Instance().Unlock(); - - return bOk; + const bool bLock = CMICmnStreamStderr::Instance().Lock(); + const bool bOk = bLock && CMICmnStreamStderr::Instance().Write(vrTxt); + bLock &&CMICmnStreamStderr::Instance().Unlock(); + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Take an LLDB message and send to the stderr stream. The message is not always -// an error message. The user has typed a command in to the Eclipse console (by- -// passing Eclipse) and this is the result message from LLDB back to the user. -// Also output to the MI Log file. -// Type: Static method. -// Args: vrTxt - (R) Text. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Take an LLDB message and send to the stderr stream. The message is not always +// an error message. The user has typed a command in to the Eclipse console (by- +// passing Eclipse) and this is the result message from LLDB back to the user. +// Also output to the MI Log file. +// Type: Static method. +// Args: vrTxt - (R) Text. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnStreamStderr::LLDBMsgToConsole( const CMIUtilString & vrTxt ) +bool +CMICmnStreamStderr::LLDBMsgToConsole(const CMIUtilString &vrTxt) { - const bool bLock = CMICmnStreamStderr::Instance().Lock(); - const bool bOk = bLock && CMICmnStreamStderr::Instance().WriteLLDBMsg( vrTxt ); - bLock && CMICmnStreamStderr::Instance().Unlock(); - - return bOk; -} + const bool bLock = CMICmnStreamStderr::Instance().Lock(); + const bool bOk = bLock && CMICmnStreamStderr::Instance().WriteLLDBMsg(vrTxt); + bLock &&CMICmnStreamStderr::Instance().Unlock(); + return bOk; +} diff --git a/tools/lldb-mi/MICmnStreamStderr.h b/tools/lldb-mi/MICmnStreamStderr.h index 45a1cf3bfc70..4fc363fa6b0a 100644 --- a/tools/lldb-mi/MICmnStreamStderr.h +++ b/tools/lldb-mi/MICmnStreamStderr.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnStreamStderr.h +// File: MICmnStreamStderr.h // -// Overview: CMICmnStreamStderr interface. +// Overview: CMICmnStreamStderr interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -28,49 +28,47 @@ #include "MIUtilThreadBaseStd.h" //++ ============================================================================ -// Details: MI common code class. The MI driver requires this object. -// CMICmnStreamStderr sets up and tears downs stderr for the driver. -// -// Singleton class. -// Gotchas: None. -// Authors: Illya Rudkin 19/03/2014. -// Changes: None. +// Details: MI common code class. The MI driver requires this object. +// CMICmnStreamStderr sets up and tears downs stderr for the driver. +// +// Singleton class. +// Gotchas: None. +// Authors: Illya Rudkin 19/03/2014. +// Changes: None. //-- -class CMICmnStreamStderr -: public CMICmnBase -, public MI::ISingleton< CMICmnStreamStderr > +class CMICmnStreamStderr : public CMICmnBase, public MI::ISingleton { - friend class MI::ISingleton< CMICmnStreamStderr >; + friend class MI::ISingleton; + + // Statics: + public: + static bool TextToStderr(const CMIUtilString &vrTxt); + static bool LLDBMsgToConsole(const CMIUtilString &vrTxt); -// Statics: -public: - static bool TextToStderr( const CMIUtilString & vrTxt ); - static bool LLDBMsgToConsole( const CMIUtilString & vrTxt ); + // Methods: + public: + bool Initialize(void); + bool Shutdown(void); + // + bool Lock(void); + bool Unlock(void); + bool Write(const CMIUtilString &vText, const bool vbSendToLog = true); + bool WriteLLDBMsg(const CMIUtilString &vText, const bool vbSendToLog = true); - // Methods: -public: - bool Initialize( void ); - bool Shutdown( void ); - // - bool Lock( void ); - bool Unlock( void ); - bool Write( const CMIUtilString & vText, const bool vbSendToLog = true ); - bool WriteLLDBMsg( const CMIUtilString & vText, const bool vbSendToLog = true ); + // Methods: + private: + /* ctor */ CMICmnStreamStderr(void); + /* ctor */ CMICmnStreamStderr(const CMICmnStreamStderr &); + void operator=(const CMICmnStreamStderr &); + // + bool WritePriv(const CMIUtilString &vText, const CMIUtilString &vTxtForLogFile, const bool vbSendToLog = true); -// Methods: -private: - /* ctor */ CMICmnStreamStderr( void ); - /* ctor */ CMICmnStreamStderr( const CMICmnStreamStderr & ); - void operator=( const CMICmnStreamStderr & ); - // - bool WritePriv( const CMIUtilString & vText, const CMIUtilString & vTxtForLogFile, const bool vbSendToLog = true ); - -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMICmnStreamStderr( void ); + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMICmnStreamStderr(void); -// Attributes: -private: - CMIUtilThreadMutex m_mutex; // Mutex object for sync during Write() + // Attributes: + private: + CMIUtilThreadMutex m_mutex; // Mutex object for sync during Write() }; diff --git a/tools/lldb-mi/MICmnStreamStdin.cpp b/tools/lldb-mi/MICmnStreamStdin.cpp index ccd3544c40f9..2d54921d323c 100644 --- a/tools/lldb-mi/MICmnStreamStdin.cpp +++ b/tools/lldb-mi/MICmnStreamStdin.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilStreamStdin.cpp +// File: MIUtilStreamStdin.cpp // -// Overview: CMICmnStreamStdin implementation. +// Overview: CMICmnStreamStdin implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -27,7 +27,7 @@ #include "MICmnThreadMgrStd.h" #include "MIUtilSingletonHelper.h" #include "MIDriver.h" -#if defined( _MSC_VER ) +#if defined(_MSC_VER) #include "MIUtilSystemWindows.h" #include "MICmnStreamStdinWindows.h" #else @@ -35,387 +35,415 @@ #endif // defined( _MSC_VER ) //++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStdin constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnStreamStdin constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnStreamStdin::CMICmnStreamStdin( void ) -: m_constStrThisThreadname( "MI stdin thread" ) -, m_pVisitor( nullptr ) -, m_strPromptCurrent( "(gdb)" ) -, m_bKeyCtrlCHit( false ) -, m_bShowPrompt( false ) -, m_bRedrawPrompt( true ) -, m_pStdinReadHandler( nullptr ) +CMICmnStreamStdin::CMICmnStreamStdin(void) + : m_constStrThisThreadname("MI stdin thread") + , m_pVisitor(nullptr) + , m_strPromptCurrent("(gdb)") + , m_bKeyCtrlCHit(false) + , m_bShowPrompt(false) + , m_bRedrawPrompt(true) + , m_pStdinReadHandler(nullptr) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStdin destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnStreamStdin destructor. +// Type: Overridable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnStreamStdin::~CMICmnStreamStdin( void ) +CMICmnStreamStdin::~CMICmnStreamStdin(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this Stdin stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialize resources for *this Stdin stream. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdin::Initialize( void ) +bool +CMICmnStreamStdin::Initialize(void) { - m_clientUsageRefCnt++; + m_clientUsageRefCnt++; - if( m_bInitialized ) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - bool bOk = MIstatus::success; - CMIUtilString errMsg; + bool bOk = MIstatus::success; + CMIUtilString errMsg; - // Note initialisation order is important here as some resources depend on previous - MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); - MI::ModuleInit< CMICmnResources > ( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg ); - MI::ModuleInit< CMICmnThreadMgrStd >( IDS_MI_INIT_ERR_THREADMGR, bOk, errMsg ); + // Note initialisation order is important here as some resources depend on previous + MI::ModuleInit(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_THREADMGR, bOk, errMsg); #ifdef _MSC_VER - MI::ModuleInit< CMICmnStreamStdinWindows >( IDS_MI_INIT_ERR_OS_STDIN_HANDLER, bOk, errMsg ); - bOk = bOk && SetOSStdinHandler( CMICmnStreamStdinWindows::Instance() ); + MI::ModuleInit(IDS_MI_INIT_ERR_OS_STDIN_HANDLER, bOk, errMsg); + bOk = bOk && SetOSStdinHandler(CMICmnStreamStdinWindows::Instance()); #else - MI::ModuleInit< CMICmnStreamStdinLinux >( IDS_MI_INIT_ERR_OS_STDIN_HANDLER, bOk, errMsg ); - bOk = bOk && SetOSStdinHandler( CMICmnStreamStdinLinux::Instance() ); + MI::ModuleInit(IDS_MI_INIT_ERR_OS_STDIN_HANDLER, bOk, errMsg); + bOk = bOk && SetOSStdinHandler(CMICmnStreamStdinLinux::Instance()); #endif // ( _MSC_VER ) - // The OS specific stdin stream handler must be set before *this class initialises - if( bOk && m_pStdinReadHandler == nullptr ) - { - CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_STREAMSTDIN_OSHANDLER ), errMsg.c_str() ) ); - SetErrorDescription( strInitError ); - return MIstatus::failure; - } - - // Other resources required - if( bOk ) - { - m_bKeyCtrlCHit = false; // Reset - } - - m_bInitialized = bOk; - - if( !bOk ) - { - CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_STREAMSTDIN ), errMsg.c_str() ) ); - SetErrorDescription( strInitError ); - return MIstatus::failure; - } - - return MIstatus::success; + // The OS specific stdin stream handler must be set before *this class initialises + if (bOk && m_pStdinReadHandler == nullptr) + { + CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_STREAMSTDIN_OSHANDLER), errMsg.c_str())); + SetErrorDescription(strInitError); + return MIstatus::failure; + } + + // Other resources required + if (bOk) + { + m_bKeyCtrlCHit = false; // Reset + } + + m_bInitialized = bOk; + + if (!bOk) + { + CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_STREAMSTDIN), errMsg.c_str())); + SetErrorDescription(strInitError); + return MIstatus::failure; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this Stdin stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Release resources for *this Stdin stream. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdin::Shutdown( void ) +bool +CMICmnStreamStdin::Shutdown(void) { - if( --m_clientUsageRefCnt > 0 ) - return MIstatus::success; - - if( !m_bInitialized ) - return MIstatus::success; + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - m_bInitialized = false; + if (!m_bInitialized) + return MIstatus::success; - ClrErrorDescription(); + m_bInitialized = false; - bool bOk = MIstatus::success; - CMIUtilString errMsg; + ClrErrorDescription(); - m_pVisitor = nullptr; - m_bKeyCtrlCHit = false; + bool bOk = MIstatus::success; + CMIUtilString errMsg; - // Note shutdown order is important here + m_pVisitor = nullptr; + m_bKeyCtrlCHit = false; + +// Note shutdown order is important here #ifndef _MSC_VER - MI::ModuleShutdown< CMICmnStreamStdinLinux >( IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, bOk, errMsg ); + MI::ModuleShutdown(IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, bOk, errMsg); #else - MI::ModuleShutdown< CMICmnStreamStdinWindows >( IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, bOk, errMsg ); + MI::ModuleShutdown(IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, bOk, errMsg); #endif // ( _MSC_VER ) - MI::ModuleShutdown< CMICmnThreadMgrStd >( IDS_MI_SHTDWN_ERR_THREADMGR, bOk, errMsg ); - MI::ModuleShutdown< CMICmnResources > ( IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg ); - MI::ModuleShutdown< CMICmnLog > ( IDS_MI_SHTDWN_ERR_LOG , bOk, errMsg ); + MI::ModuleShutdown(IDS_MI_SHTDWN_ERR_THREADMGR, bOk, errMsg); + MI::ModuleShutdown(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg); - if( !bOk ) - { - SetErrorDescriptionn( MIRSRC( IDE_MI_SHTDWN_ERR_STREAMSTDIN ), errMsg.c_str() ); - } + if (!bOk) + { + SetErrorDescriptionn(MIRSRC(IDE_MI_SHTDWN_ERR_STREAMSTDIN), errMsg.c_str()); + } - return MIstatus::success; -} + return MIstatus::success; +} //++ ------------------------------------------------------------------------------------ -// Details: Validate and set the text that forms the prompt on the command line. -// Type: Method. -// Args: vNewPrompt - (R) Text description. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Validate and set the text that forms the prompt on the command line. +// Type: Method. +// Args: vNewPrompt - (R) Text description. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdin::SetPrompt( const CMIUtilString & vNewPrompt ) +bool +CMICmnStreamStdin::SetPrompt(const CMIUtilString &vNewPrompt) { - if( vNewPrompt.empty() ) - { - const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_STDIN_ERR_INVALID_PROMPT), vNewPrompt.c_str() ) ); - CMICmnStreamStdout::Instance().Write( msg ); - return MIstatus::failure; - } + if (vNewPrompt.empty()) + { + const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_STDIN_ERR_INVALID_PROMPT), vNewPrompt.c_str())); + CMICmnStreamStdout::Instance().Write(msg); + return MIstatus::failure; + } - m_strPromptCurrent = vNewPrompt; + m_strPromptCurrent = vNewPrompt; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the command line prompt text currently being used. -// Type: Method. -// Args: None. -// Return: const CMIUtilString & - Functional failed. -// Throws: None. +// Details: Retrieve the command line prompt text currently being used. +// Type: Method. +// Args: None. +// Return: const CMIUtilString & - Functional failed. +// Throws: None. //-- -const CMIUtilString & CMICmnStreamStdin::GetPrompt( void ) const +const CMIUtilString & +CMICmnStreamStdin::GetPrompt(void) const { - return m_strPromptCurrent; + return m_strPromptCurrent; } //++ ------------------------------------------------------------------------------------ -// Details: Wait on input from stream Stdin. On each line of input received it is -// validated and providing there are no errors on the stream or the input -// buffer is not exceeded the data is passed to the visitor. -// Type: Method. -// Args: vrVisitor - (W) A client deriver callback. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Wait on input from stream Stdin. On each line of input received it is +// validated and providing there are no errors on the stream or the input +// buffer is not exceeded the data is passed to the visitor. +// Type: Method. +// Args: vrVisitor - (W) A client deriver callback. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdin::SetVisitor( IStreamStdin & vrVisitor ) +bool +CMICmnStreamStdin::SetVisitor(IStreamStdin &vrVisitor) { - m_pVisitor = &vrVisitor; - return MIstatus::success; + m_pVisitor = &vrVisitor; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Set whether to display optional command line prompt. The prompt is output to -// stdout. Disable it when this may interfere with the client reading stdout as -// input and it tries to interpret the prompt text to. -// Type: Method. -// Args: vbYes - (R) True = Yes prompt is shown/output to the user (stdout), false = no prompt. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// stdout. Disable it when this may interfere with the client reading stdout as +// input and it tries to interpret the prompt text to. +// Type: Method. +// Args: vbYes - (R) True = Yes prompt is shown/output to the user (stdout), false = no prompt. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -void CMICmnStreamStdin::SetEnablePrompt( const bool vbYes ) +void +CMICmnStreamStdin::SetEnablePrompt(const bool vbYes) { - m_bShowPrompt = vbYes; + m_bShowPrompt = vbYes; } //++ ------------------------------------------------------------------------------------ // Details: Get whether to display optional command line prompt. The prompt is output to -// stdout. Disable it when this may interfere with the client reading stdout as -// input and it tries to interpret the prompt text to. -// Type: Method. -// Args: None. -// Return: bool - True = Yes prompt is shown/output to the user (stdout), false = no prompt. -// Throws: None. +// stdout. Disable it when this may interfere with the client reading stdout as +// input and it tries to interpret the prompt text to. +// Type: Method. +// Args: None. +// Return: bool - True = Yes prompt is shown/output to the user (stdout), false = no prompt. +// Throws: None. //-- -bool CMICmnStreamStdin::GetEnablePrompt( void ) const +bool +CMICmnStreamStdin::GetEnablePrompt(void) const { - return m_bShowPrompt; + return m_bShowPrompt; } //++ ------------------------------------------------------------------------------------ -// Details: Determine if stdin has any characters present in its buffer. -// Type: Method. -// Args: vwbAvail - (W) True = There is chars available, false = nothing there. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Determine if stdin has any characters present in its buffer. +// Type: Method. +// Args: vwbAvail - (W) True = There is chars available, false = nothing there. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdin::InputAvailable( bool & vwbAvail ) +bool +CMICmnStreamStdin::InputAvailable(bool &vwbAvail) { - return m_pStdinReadHandler->InputAvailable( vwbAvail ); + return m_pStdinReadHandler->InputAvailable(vwbAvail); } //++ ------------------------------------------------------------------------------------ -// Details: The monitoring on new line data calls back to the visitor object registered -// with *this stdin monitoring. The monitoring to stops when the visitor returns -// true for bYesExit flag. Errors output to log file. -// This function runs in the thread "MI stdin monitor". -// Type: Method. -// vrwbYesAlive - (W) False = yes exit stdin monitoring, true = continue monitor. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The monitoring on new line data calls back to the visitor object registered +// with *this stdin monitoring. The monitoring to stops when the visitor returns +// true for bYesExit flag. Errors output to log file. +// This function runs in the thread "MI stdin monitor". +// Type: Method. +// vrwbYesAlive - (W) False = yes exit stdin monitoring, true = continue monitor. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdin::MonitorStdin( bool & vrwbYesAlive ) +bool +CMICmnStreamStdin::MonitorStdin(bool &vrwbYesAlive) { - if( m_bShowPrompt ) - { - CMICmnStreamStdout & rStdoutMan = CMICmnStreamStdout::Instance(); - rStdoutMan.WriteMIResponse( m_strPromptCurrent.c_str() ); - m_bRedrawPrompt = false; - } - - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - if( m_bKeyCtrlCHit ) - { - CMIDriver & rMIDriver = CMIDriver::Instance(); - rMIDriver.SetExitApplicationFlag( false ); - if( rMIDriver.GetExitApplicationFlag() ) - { - vrwbYesAlive = false; - return MIstatus::success; - } - - // Reset - the MI Driver received SIGINT during a running debug programm session - m_bKeyCtrlCHit = false; - } + if (m_bShowPrompt) + { + CMICmnStreamStdout &rStdoutMan = CMICmnStreamStdout::Instance(); + rStdoutMan.WriteMIResponse(m_strPromptCurrent.c_str()); + m_bRedrawPrompt = false; + } + + // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM + if (m_bKeyCtrlCHit) + { + CMIDriver &rMIDriver = CMIDriver::Instance(); + rMIDriver.SetExitApplicationFlag(false); + if (rMIDriver.GetExitApplicationFlag()) + { + vrwbYesAlive = false; + return MIstatus::success; + } + + // Reset - the MI Driver received SIGINT during a running debug programm session + m_bKeyCtrlCHit = false; + } #if MICONFIG_POLL_FOR_STD_IN - bool bAvail = true; - // Check if there is stdin available - if( InputAvailable( bAvail ) ) - { - // Early exit when there is no input - if( !bAvail ) - return MIstatus::success; - } - else - { - vrwbYesAlive = false; - CMIDriver::Instance().SetExitApplicationFlag( true ); - return MIstatus::failure; - } + bool bAvail = true; + // Check if there is stdin available + if (InputAvailable(bAvail)) + { + // Early exit when there is no input + if (!bAvail) + return MIstatus::success; + } + else + { + vrwbYesAlive = false; + CMIDriver::Instance().SetExitApplicationFlag(true); + return MIstatus::failure; + } #endif // MICONFIG_POLL_FOR_STD_IN - // Read a line from std input - CMIUtilString stdinErrMsg; - const MIchar * pText = ReadLine( stdinErrMsg ); - - // Did something go wrong - const bool bHaveError( !stdinErrMsg.empty() ); - if( (pText == nullptr) || bHaveError ) - { - if( bHaveError ) - { - CMICmnStreamStdout::Instance().Write( stdinErrMsg ); - } - return MIstatus::failure; - } - - // We have text so send it off to the visitor - bool bOk = MIstatus::success; - if( m_pVisitor != nullptr ) - { - bool bYesExit = false; - bOk = m_pVisitor->ReadLine( CMIUtilString( pText ), bYesExit ); - m_bRedrawPrompt = true; - vrwbYesAlive = !bYesExit; - } - - return bOk; + // Read a line from std input + CMIUtilString stdinErrMsg; + const MIchar *pText = ReadLine(stdinErrMsg); + + // Did something go wrong + const bool bHaveError(!stdinErrMsg.empty()); + if ((pText == nullptr) || bHaveError) + { + if (bHaveError) + { + CMICmnStreamStdout::Instance().Write(stdinErrMsg); + } + return MIstatus::failure; + } + + // We have text so send it off to the visitor + bool bOk = MIstatus::success; + if (m_pVisitor != nullptr) + { + bool bYesExit = false; + bOk = m_pVisitor->ReadLine(CMIUtilString(pText), bYesExit); + m_bRedrawPrompt = true; + vrwbYesAlive = !bYesExit; + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Wait on new line of data from stdin stream (completed by '\n' or '\r'). -// Type: Method. -// Args: vwErrMsg - (W) Empty string ok or error description. -// Return: MIchar * - text buffer pointer or NULL on failure. -// Throws: None. +// Details: Wait on new line of data from stdin stream (completed by '\n' or '\r'). +// Type: Method. +// Args: vwErrMsg - (W) Empty string ok or error description. +// Return: MIchar * - text buffer pointer or NULL on failure. +// Throws: None. //-- -const MIchar * CMICmnStreamStdin::ReadLine( CMIUtilString & vwErrMsg ) +const MIchar * +CMICmnStreamStdin::ReadLine(CMIUtilString &vwErrMsg) { - return m_pStdinReadHandler->ReadLine( vwErrMsg ); + return m_pStdinReadHandler->ReadLine(vwErrMsg); } //++ ------------------------------------------------------------------------------------ -// Details: Inform *this stream that the user hit Control-C key to exit. -// The function is normally called by the SIGINT signal in sigint_handler() to -// simulate kill app from the client. -// This function is called by a Kernel thread. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: Inform *this stream that the user hit Control-C key to exit. +// The function is normally called by the SIGINT signal in sigint_handler() to +// simulate kill app from the client. +// This function is called by a Kernel thread. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMICmnStreamStdin::SetCtrlCHit( void ) +void +CMICmnStreamStdin::SetCtrlCHit(void) { - CMIUtilThreadLock lock( m_mutex ); - m_bKeyCtrlCHit = true; + CMIUtilThreadLock lock(m_mutex); + m_bKeyCtrlCHit = true; } //++ ------------------------------------------------------------------------------------ -// Details: The main worker method for this thread. -// Type: Overridden. -// Args: vrbIsAlive = (W) True = *this thread is working, false = thread has exited. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: The main worker method for this thread. +// Type: Overridden. +// Args: vrbIsAlive - (W) True = *this thread is working, false = thread has exited. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdin::ThreadRun( bool & vrbIsAlive ) +bool +CMICmnStreamStdin::ThreadRun(bool &vrbIsAlive) { - return MonitorStdin( vrbIsAlive ); + return MonitorStdin(vrbIsAlive); } //++ ------------------------------------------------------------------------------------ -// Details: Let this thread clean up after itself. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Let this thread clean up after itself. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdin::ThreadFinish( void ) +bool +CMICmnStreamStdin::ThreadFinish(void) { - // Do nothing - override to implement - return MIstatus::success; + // Do nothing - override to implement + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve *this thread object's name. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString & - Text. -// Throws: None. +// Details: Retrieve *this thread object's name. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString & - Text. +// Throws: None. //-- -const CMIUtilString & CMICmnStreamStdin::ThreadGetName( void ) const +const CMIUtilString & +CMICmnStreamStdin::ThreadGetName(void) const { - return m_constStrThisThreadname; + return m_constStrThisThreadname; } //++ ------------------------------------------------------------------------------------ -// Details: Mandatory set the OS specific stream stdin handler. *this class utilises the -// handler to read data from the stdin stream and put into a queue for the -// driver to read when able. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Mandatory set the OS specific stream stdin handler. *this class utilises the +// handler to read data from the stdin stream and put into a queue for the +// driver to read when able. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdin::SetOSStdinHandler( IOSStdinHandler & vrHandler ) +bool +CMICmnStreamStdin::SetOSStdinHandler(IOSStdinHandler &vrHandler) { - m_pStdinReadHandler = &vrHandler; + m_pStdinReadHandler = &vrHandler; + + return MIstatus::success; +} - return MIstatus::success; +//++ ------------------------------------------------------------------------------------ +// Details: Do some actions before exiting. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. +//-- +void +CMICmnStreamStdin::OnExitHandler(void) +{ + m_pStdinReadHandler->InterruptReadLine(); } diff --git a/tools/lldb-mi/MICmnStreamStdin.h b/tools/lldb-mi/MICmnStreamStdin.h index edd79f60b8d4..a6779d531669 100644 --- a/tools/lldb-mi/MICmnStreamStdin.h +++ b/tools/lldb-mi/MICmnStreamStdin.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilStreamStdin.h +// File: MIUtilStreamStdin.h // -// Overview: CMICmnStreamStdin interface. +// Overview: CMICmnStreamStdin interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -28,98 +28,98 @@ #include "MIUtilSingletonBase.h" //++ ============================================================================ -// Details: MI common code class. Used to handle stream data from Stdin. -// Singleton class using the Visitor pattern. A driver using the interface -// provide can receive callbacks when a new line of data is received. -// Each line is determined by a carriage return. -// A singleton class. -// Gotchas: None. -// Authors: Illya Rudkin 10/02/2014. -// Changes: Factored out OS specific handling of reading stdin - IOR 16/06/2014. +// Details: MI common code class. Used to handle stream data from Stdin. +// Singleton class using the Visitor pattern. A driver using the interface +// provide can receive callbacks when a new line of data is received. +// Each line is determined by a carriage return. +// A singleton class. +// Gotchas: None. +// Authors: Illya Rudkin 10/02/2014. +// Changes: Factored out OS specific handling of reading stdin - IOR 16/06/2014. //-- -class CMICmnStreamStdin -: public CMICmnBase -, public CMIUtilThreadActiveObjBase -, public MI::ISingleton< CMICmnStreamStdin > +class CMICmnStreamStdin : public CMICmnBase, public CMIUtilThreadActiveObjBase, public MI::ISingleton { - // Give singleton access to private constructors - friend MI::ISingleton< CMICmnStreamStdin >; + // Give singleton access to private constructors + friend MI::ISingleton; -// Class: -public: - //++ - // Description: Visitor pattern. Driver(s) use this interface to get a callback - // on each new line of data received from stdin. - //-- - class IStreamStdin - { - public: - virtual bool ReadLine( const CMIUtilString & vStdInBuffer, bool & vrwbYesExit ) = 0; + // Class: + public: + //++ + // Description: Visitor pattern. Driver(s) use this interface to get a callback + // on each new line of data received from stdin. + //-- + class IStreamStdin + { + public: + virtual bool ReadLine(const CMIUtilString &vStdInBuffer, bool &vrwbYesExit) = 0; - /* dtor */ virtual ~IStreamStdin( void ) {}; - }; + /* dtor */ virtual ~IStreamStdin(void){}; + }; - //++ - // Description: Specific OS stdin handling implementations are created and used by *this - // class. Seperates out functionality and enables handler to be set - // dynamically depended on the OS detected. - //-- - class IOSStdinHandler - { - public: - virtual bool InputAvailable( bool & vwbAvail ) = 0; - virtual const MIchar * ReadLine( CMIUtilString & vwErrMsg ) = 0; + //++ + // Description: Specific OS stdin handling implementations are created and used by *this + // class. Seperates out functionality and enables handler to be set + // dynamically depended on the OS detected. + //-- + class IOSStdinHandler + { + public: + virtual bool InputAvailable(bool &vwbAvail) = 0; + virtual const MIchar *ReadLine(CMIUtilString &vwErrMsg) = 0; + virtual void InterruptReadLine(void){}; - /* dtor */ virtual ~IOSStdinHandler( void ) {}; - }; - -// Methods: -public: - bool Initialize( void ); - bool Shutdown( void ); - // - const CMIUtilString & GetPrompt( void ) const; - bool SetPrompt( const CMIUtilString & vNewPrompt ); - void SetEnablePrompt( const bool vbYes ); - bool GetEnablePrompt( void ) const; - void SetCtrlCHit( void ); - bool SetVisitor( IStreamStdin & vrVisitor ); - bool SetOSStdinHandler( IOSStdinHandler & vrHandler ); - -// Overridden: -public: - // From CMIUtilThreadActiveObjBase - virtual const CMIUtilString & ThreadGetName( void ) const; - -// Overridden: -protected: - // From CMIUtilThreadActiveObjBase - virtual bool ThreadRun( bool & vrIsAlive ); - virtual bool ThreadFinish( void ); // Let this thread clean up after itself + /* dtor */ virtual ~IOSStdinHandler(void){}; + }; -// Methods: -private: - /* ctor */ CMICmnStreamStdin( void ); - /* ctor */ CMICmnStreamStdin( const CMICmnStreamStdin & ); - void operator=( const CMICmnStreamStdin & ); - - bool MonitorStdin( bool & vrwbYesExit ); - const MIchar * ReadLine( CMIUtilString & vwErrMsg ); - bool InputAvailable( bool & vbAvail ); // Bytes are available on stdin + // Methods: + public: + bool Initialize(void); + bool Shutdown(void); + // + const CMIUtilString &GetPrompt(void) const; + bool SetPrompt(const CMIUtilString &vNewPrompt); + void SetEnablePrompt(const bool vbYes); + bool GetEnablePrompt(void) const; + void SetCtrlCHit(void); + bool SetVisitor(IStreamStdin &vrVisitor); + bool SetOSStdinHandler(IOSStdinHandler &vrHandler); + void OnExitHandler(void); -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMICmnStreamStdin( void ); + // Overridden: + public: + // From CMIUtilThreadActiveObjBase + virtual const CMIUtilString &ThreadGetName(void) const; -// Attributes: -private: - const CMIUtilString m_constStrThisThreadname; - IStreamStdin * m_pVisitor; - CMIUtilString m_strPromptCurrent; // Command line prompt as shown to the user - volatile bool m_bKeyCtrlCHit; // True = User hit Ctrl-C, false = has not yet - bool m_bShowPrompt; // True = Yes prompt is shown/output to the user (stdout), false = no prompt - bool m_bRedrawPrompt; // True = Prompt needs to be redrawn - IOSStdinHandler * m_pStdinReadHandler; -}; + // Overridden: + protected: + // From CMIUtilThreadActiveObjBase + virtual bool ThreadRun(bool &vrIsAlive); + virtual bool + ThreadFinish(void); // Let this thread clean up after itself + + // Methods: + private: + /* ctor */ CMICmnStreamStdin(void); + /* ctor */ CMICmnStreamStdin(const CMICmnStreamStdin &); + void operator=(const CMICmnStreamStdin &); + + bool MonitorStdin(bool &vrwbYesExit); + const MIchar *ReadLine(CMIUtilString &vwErrMsg); + bool + InputAvailable(bool &vbAvail); // Bytes are available on stdin + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMICmnStreamStdin(void); + + // Attributes: + private: + const CMIUtilString m_constStrThisThreadname; + IStreamStdin *m_pVisitor; + CMIUtilString m_strPromptCurrent; // Command line prompt as shown to the user + volatile bool m_bKeyCtrlCHit; // True = User hit Ctrl-C, false = has not yet + bool m_bShowPrompt; // True = Yes prompt is shown/output to the user (stdout), false = no prompt + bool m_bRedrawPrompt; // True = Prompt needs to be redrawn + IOSStdinHandler *m_pStdinReadHandler; +}; diff --git a/tools/lldb-mi/MICmnStreamStdinLinux.cpp b/tools/lldb-mi/MICmnStreamStdinLinux.cpp index f73dc32d8258..07e652d84c19 100644 --- a/tools/lldb-mi/MICmnStreamStdinLinux.cpp +++ b/tools/lldb-mi/MICmnStreamStdinLinux.cpp @@ -8,22 +8,22 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilStreamStdin.cpp +// File: MIUtilStreamStdin.cpp // -// Overview: CMICmnStreamStdinLinux implementation. +// Overview: CMICmnStreamStdinLinux implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third Party Headers: -#if !defined( _MSC_VER ) +#if defined(__APPLE__) #include -#include -#endif // !defined( _MSC_VER ) +#include // For STDIN_FILENO +#endif // defined( __APPLE__ ) #include // For std::strerror() // In-house headers: @@ -33,180 +33,193 @@ #include "MIUtilSingletonHelper.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStdinLinux constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnStreamStdinLinux constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnStreamStdinLinux::CMICmnStreamStdinLinux( void ) -: m_constBufferSize( 1024 ) -, m_pStdin( nullptr ) -, m_pCmdBuffer( nullptr ) +CMICmnStreamStdinLinux::CMICmnStreamStdinLinux(void) + : m_constBufferSize(1024) + , m_pStdin(nullptr) + , m_pCmdBuffer(nullptr) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStdinLinux destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnStreamStdinLinux destructor. +// Type: Overridable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnStreamStdinLinux::~CMICmnStreamStdinLinux( void ) +CMICmnStreamStdinLinux::~CMICmnStreamStdinLinux(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this Stdin stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialize resources for *this Stdin stream. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdinLinux::Initialize( void ) +bool +CMICmnStreamStdinLinux::Initialize(void) { - if( m_bInitialized ) - return MIstatus::success; - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Note initialisation order is important here as some resources depend on previous - MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); - MI::ModuleInit< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg ); - - // Other resources required - if( bOk ) - { - m_pCmdBuffer = new MIchar[ m_constBufferSize ]; - m_pStdin = stdin; - } - - // Clear error indicators for std input - ::clearerr( stdin ); - - m_bInitialized = bOk; - - if( !bOk ) - { - CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_OS_STDIN_HANDLER ), errMsg.c_str() ) ); - SetErrorDescription( strInitError ); - return MIstatus::failure; - } - - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; + + bool bOk = MIstatus::success; + CMIUtilString errMsg; + + // Note initialisation order is important here as some resources depend on previous + MI::ModuleInit(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + + // Other resources required + if (bOk) + { + m_pCmdBuffer = new MIchar[m_constBufferSize]; + m_pStdin = stdin; + } + + // Clear error indicators for std input + ::clearerr(stdin); + + m_bInitialized = bOk; + + if (!bOk) + { + CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_OS_STDIN_HANDLER), errMsg.c_str())); + SetErrorDescription(strInitError); + return MIstatus::failure; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this Stdin stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Release resources for *this Stdin stream. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdinLinux::Shutdown( void ) +bool +CMICmnStreamStdinLinux::Shutdown(void) { - if( !m_bInitialized ) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - m_bInitialized = false; + m_bInitialized = false; - ClrErrorDescription(); + ClrErrorDescription(); - bool bOk = MIstatus::success; - CMIUtilString errMsg; + bool bOk = MIstatus::success; + CMIUtilString errMsg; - // Tidy up - if( m_pCmdBuffer != nullptr ) - { - delete [] m_pCmdBuffer; - m_pCmdBuffer = nullptr; - } - m_pStdin = nullptr; + // Tidy up + if (m_pCmdBuffer != nullptr) + { + delete[] m_pCmdBuffer; + m_pCmdBuffer = nullptr; + } + m_pStdin = nullptr; - // Note shutdown order is important here - MI::ModuleShutdown< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg ); - MI::ModuleShutdown< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); + // Note shutdown order is important here + MI::ModuleShutdown(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - if( !bOk ) - { - SetErrorDescriptionn( MIRSRC( IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER ), errMsg.c_str() ); - } + if (!bOk) + { + SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER), errMsg.c_str()); + } - return MIstatus::success; -} + return MIstatus::success; +} //++ ------------------------------------------------------------------------------------ -// Details: Determine if stdin has any characters present in its buffer. -// Type: Method. -// Args: vwbAvail - (W) True = There is chars available, false = nothing there. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Determine if stdin has any characters present in its buffer. +// Type: Method. +// Args: vwbAvail - (W) True = There is chars available, false = nothing there. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdinLinux::InputAvailable( bool & vwbAvail ) +bool +CMICmnStreamStdinLinux::InputAvailable(bool &vwbAvail) { -/* AD: Not used ATM but could come in handy just in case we need to do - this, poll for input - - static const int STDIN = 0; - static bool bInitialized = false; - - if( !bInitialized ) - { - // Use termios to turn off line buffering - ::termios term; - ::tcgetattr( STDIN, &term ); - ::term.c_lflag &= ~ICANON; - ::tcsetattr( STDIN, TCSANOW, &term ); - ::setbuf( stdin, NULL ); - bInitialized = true; +#if defined(__APPLE__) + // The code below is needed on OSX where lldb-mi hangs when doing -exec-run. + // The hang seems to come from calling fgets and fileno from different thread. + // Although this problem was not observed on Linux. + // A solution based on 'ioctl' was initially committed but it seems to make + // lldb-mi takes much more processor time. The solution based on 'select' works + // well but it seems to slow the execution of lldb-mi tests a lot on Linux. + // As a result, this code is #defined to run only on OSX. + fd_set setOfStdin; + FD_ZERO(&setOfStdin); + FD_SET(STDIN_FILENO, &setOfStdin); + + // Wait while input would be available + if (::select(STDIN_FILENO + 1, &setOfStdin, nullptr, nullptr, nullptr) == -1) + { + vwbAvail = false; + return MIstatus::failure; } - int nBytesWaiting; - ::ioctl( STDIN, FIONREAD, &nBytesWaiting ); - vwbAvail = (nBytesWaiting > 0); - - return MIstatus::success; -*/ - - return MIstatus::success; +#endif // defined( __APPLE__ ) + vwbAvail = true; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Wait on new line of data from stdin stream (completed by '\n' or '\r'). -// Type: Method. -// Args: vwErrMsg - (W) Empty string ok or error description. -// Return: MIchar * - text buffer pointer or NULL on failure. -// Throws: None. +// Details: Wait on new line of data from stdin stream (completed by '\n' or '\r'). +// Type: Method. +// Args: vwErrMsg - (W) Empty string ok or error description. +// Return: MIchar * - text buffer pointer or NULL on failure. +// Throws: None. //-- -const MIchar * CMICmnStreamStdinLinux::ReadLine( CMIUtilString & vwErrMsg ) +const MIchar * +CMICmnStreamStdinLinux::ReadLine(CMIUtilString &vwErrMsg) { - vwErrMsg.clear(); - - // Read user input - const MIchar * pText = ::fgets( &m_pCmdBuffer[ 0 ], m_constBufferSize, stdin ); - if( pText == nullptr ) - { - if( ::ferror( m_pStdin ) != 0 ) - vwErrMsg = ::strerror( errno ); - return nullptr; - } + vwErrMsg.clear(); + + // Read user input + const MIchar *pText = ::fgets(&m_pCmdBuffer[0], m_constBufferSize, stdin); + if (pText == nullptr) + { + if (::ferror(m_pStdin) != 0) + vwErrMsg = ::strerror(errno); + return nullptr; + } // Strip off new line characters - for( MIchar * pI = m_pCmdBuffer; *pI != '\0'; pI++ ) - { - if( (*pI == '\n') || (*pI == '\r') ) - { - *pI = '\0'; - break; - } - } - - return pText; + for (MIchar *pI = m_pCmdBuffer; *pI != '\0'; pI++) + { + if ((*pI == '\n') || (*pI == '\r')) + { + *pI = '\0'; + break; + } + } + + return pText; } +//++ ------------------------------------------------------------------------------------ +// Details: Interrupt current and prevent new ReadLine operations. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. +//-- +void +CMICmnStreamStdinLinux::InterruptReadLine(void) +{ + fclose(stdin); +} diff --git a/tools/lldb-mi/MICmnStreamStdinLinux.h b/tools/lldb-mi/MICmnStreamStdinLinux.h index 78d796634b34..edac94034f57 100644 --- a/tools/lldb-mi/MICmnStreamStdinLinux.h +++ b/tools/lldb-mi/MICmnStreamStdinLinux.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilStreamStdin.h +// File: MIUtilStreamStdin.h // -// Overview: CMICmnStreamStdinLinux interface. +// Overview: CMICmnStreamStdinLinux interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -27,49 +27,46 @@ #include "MIUtilSingletonBase.h" //++ ============================================================================ -// Details: MI common code class. Specific OS stdin handling implementation. -// CMICmnStreamStdin instance is set with stdin handler before using the -// the stream. An instance of this class must be set up and ready to give -// to the CMICmnStreamStdin before it initialises other CMICmnStreamStdin -// will give an error. -// Gotchas: None. -// Authors: Illya Rudkin 16/06/2014. -// Changes: None. +// Details: MI common code class. Specific OS stdin handling implementation. +// CMICmnStreamStdin instance is set with stdin handler before using the +// the stream. An instance of this class must be set up and ready to give +// to the CMICmnStreamStdin before it initialises other CMICmnStreamStdin +// will give an error. +// Gotchas: None. +// Authors: Illya Rudkin 16/06/2014. +// Changes: None. //-- -class CMICmnStreamStdinLinux -: public CMICmnBase -, public CMICmnStreamStdin::IOSStdinHandler -, public MI::ISingleton< CMICmnStreamStdinLinux > +class CMICmnStreamStdinLinux : public CMICmnBase, public CMICmnStreamStdin::IOSStdinHandler, public MI::ISingleton { - // Give singleton access to private constructors - friend MI::ISingleton< CMICmnStreamStdinLinux >; + // Give singleton access to private constructors + friend MI::ISingleton; -// Methods: -public: - bool Initialize( void ); - bool Shutdown( void ); + // Methods: + public: + bool Initialize(void); + bool Shutdown(void); -// Overridden: -public: - // From CMICmnStreamStdin::IOSpecificReadStreamStdin - virtual bool InputAvailable( bool & vwbAvail ); - virtual const MIchar * ReadLine( CMIUtilString & vwErrMsg ); - -// Methods: -private: - /* ctor */ CMICmnStreamStdinLinux( void ); - /* ctor */ CMICmnStreamStdinLinux( const CMICmnStreamStdin & ); - void operator=( const CMICmnStreamStdin & ); + // Overridden: + public: + // From CMICmnStreamStdin::IOSpecificReadStreamStdin + virtual bool InputAvailable(bool &vwbAvail); + virtual const MIchar *ReadLine(CMIUtilString &vwErrMsg); + virtual void InterruptReadLine(void); -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMICmnStreamStdinLinux( void ); + // Methods: + private: + /* ctor */ CMICmnStreamStdinLinux(void); + /* ctor */ CMICmnStreamStdinLinux(const CMICmnStreamStdin &); + void operator=(const CMICmnStreamStdin &); -// Attributes: -private: - const MIuint m_constBufferSize; - FILE * m_pStdin; - MIchar * m_pCmdBuffer; -}; + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMICmnStreamStdinLinux(void); + // Attributes: + private: + const MIuint m_constBufferSize; + FILE *m_pStdin; + MIchar *m_pCmdBuffer; +}; diff --git a/tools/lldb-mi/MICmnStreamStdinWindows.cpp b/tools/lldb-mi/MICmnStreamStdinWindows.cpp index 2b24df8d61a6..8d5a3e8aa7c9 100644 --- a/tools/lldb-mi/MICmnStreamStdinWindows.cpp +++ b/tools/lldb-mi/MICmnStreamStdinWindows.cpp @@ -8,19 +8,19 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilStreamStdin.cpp +// File: MIUtilStreamStdin.cpp // -// Overview: CMICmnStreamStdinWindows implementation. +// Overview: CMICmnStreamStdinWindows implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third Party Headers: -#if defined( _MSC_VER ) +#if defined(_MSC_VER) #include #include #include @@ -36,164 +36,168 @@ #include "MIUtilSingletonHelper.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStdinWindows constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnStreamStdinWindows constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnStreamStdinWindows::CMICmnStreamStdinWindows( void ) -: m_constBufferSize( 1024 ) -, m_pStdin( nullptr ) -, m_pCmdBuffer( nullptr ) -, m_pStdinBuffer( nullptr ) -, m_nBytesToBeRead( 0 ) -, m_bRunningInConsoleWin( false ) +CMICmnStreamStdinWindows::CMICmnStreamStdinWindows(void) + : m_constBufferSize(1024) + , m_pStdin(nullptr) + , m_pCmdBuffer(nullptr) + , m_pStdinBuffer(nullptr) + , m_nBytesToBeRead(0) + , m_bRunningInConsoleWin(false) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStdinWindows destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnStreamStdinWindows destructor. +// Type: Overridable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnStreamStdinWindows::~CMICmnStreamStdinWindows( void ) +CMICmnStreamStdinWindows::~CMICmnStreamStdinWindows(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this Stdin stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialize resources for *this Stdin stream. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdinWindows::Initialize( void ) +bool +CMICmnStreamStdinWindows::Initialize(void) { - if( m_bInitialized ) - return MIstatus::success; - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Note initialisation order is important here as some resources depend on previous - MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); - MI::ModuleInit< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg ); - - // Other resources required - if( bOk ) - { - m_pCmdBuffer = new MIchar[ m_constBufferSize ]; - m_pStdin = stdin; + if (m_bInitialized) + return MIstatus::success; + + bool bOk = MIstatus::success; + CMIUtilString errMsg; + + // Note initialisation order is important here as some resources depend on previous + MI::ModuleInit(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + + // Other resources required + if (bOk) + { + m_pCmdBuffer = new MIchar[m_constBufferSize]; + m_pStdin = stdin; #if MICONFIG_CREATE_OWN_STDIN_BUFFER - // Give stdinput a user defined buffer - m_pStdinBuffer = new char[ 1024 ]; - ::setbuf( stdin, m_pStdinBuffer ); + // Give stdinput a user defined buffer + m_pStdinBuffer = new char[1024]; + ::setbuf(stdin, m_pStdinBuffer); #endif // MICONFIG_CREATE_OWN_STDIN_BUFFER - // Clear error indicators for std input - ::clearerr( stdin ); + // Clear error indicators for std input + ::clearerr(stdin); -#if defined( _MSC_VER ) - m_bRunningInConsoleWin = ::_isatty( ::fileno( stdin ) ); +#if defined(_MSC_VER) + m_bRunningInConsoleWin = ::_isatty(::fileno(stdin)); #endif // #if defined( _MSC_VER ) - } + } - m_bInitialized = bOk; + m_bInitialized = bOk; - if( !bOk ) - { - CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_OS_STDIN_HANDLER ), errMsg.c_str() ) ); - SetErrorDescription( strInitError ); - return MIstatus::failure; - } + if (!bOk) + { + CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_OS_STDIN_HANDLER), errMsg.c_str())); + SetErrorDescription(strInitError); + return MIstatus::failure; + } - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this Stdin stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Release resources for *this Stdin stream. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdinWindows::Shutdown( void ) +bool +CMICmnStreamStdinWindows::Shutdown(void) { - if( !m_bInitialized ) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - m_bInitialized = false; + m_bInitialized = false; - ClrErrorDescription(); + ClrErrorDescription(); - bool bOk = MIstatus::success; - CMIUtilString errMsg; + bool bOk = MIstatus::success; + CMIUtilString errMsg; - // Tidy up - if( m_pCmdBuffer != nullptr ) - { - delete [] m_pCmdBuffer; - m_pCmdBuffer = nullptr; - } - m_pStdin = nullptr; + // Tidy up + if (m_pCmdBuffer != nullptr) + { + delete[] m_pCmdBuffer; + m_pCmdBuffer = nullptr; + } + m_pStdin = nullptr; #if MICONFIG_CREATE_OWN_STDIN_BUFFER - if ( m_pStdinBuffer ) - delete [] m_pStdinBuffer; - m_pStdinBuffer = nullptr; + if (m_pStdinBuffer) + delete[] m_pStdinBuffer; + m_pStdinBuffer = nullptr; #endif // MICONFIG_CREATE_OWN_STDIN_BUFFER - // Note shutdown order is important here - MI::ModuleShutdown< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg ); - MI::ModuleShutdown< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); + // Note shutdown order is important here + MI::ModuleShutdown(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - if( !bOk ) - { - SetErrorDescriptionn( MIRSRC( IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER ), errMsg.c_str() ); - } + if (!bOk) + { + SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER), errMsg.c_str()); + } - return MIstatus::success; -} + return MIstatus::success; +} //++ ------------------------------------------------------------------------------------ -// Details: Determine if stdin has any characters present in its buffer. -// Type: Method. -// Args: vwbAvail - (W) True = There is chars available, false = nothing there. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Determine if stdin has any characters present in its buffer. +// Type: Method. +// Args: vwbAvail - (W) True = There is chars available, false = nothing there. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdinWindows::InputAvailable( bool & vwbAvail ) +bool +CMICmnStreamStdinWindows::InputAvailable(bool &vwbAvail) { - return m_bRunningInConsoleWin ? InputAvailableConsoleWin( vwbAvail ) : InputAvailableApplication( vwbAvail ); + return m_bRunningInConsoleWin ? InputAvailableConsoleWin(vwbAvail) : InputAvailableApplication(vwbAvail); } //++ ------------------------------------------------------------------------------------ -// Details: Determine if stdin has any characters present in its buffer. If running in a -// terminal use _kbhit(). -// Type: Method. -// Args: vwbAvail - (W) True = There is chars available, false = nothing there. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Determine if stdin has any characters present in its buffer. If running in a +// terminal use _kbhit(). +// Type: Method. +// Args: vwbAvail - (W) True = There is chars available, false = nothing there. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdinWindows::InputAvailableConsoleWin( bool & vwbAvail ) +bool +CMICmnStreamStdinWindows::InputAvailableConsoleWin(bool &vwbAvail) { -#if defined( _MSC_VER ) - if( m_nBytesToBeRead == 0 ) - { +#if defined(_MSC_VER) + if (m_nBytesToBeRead == 0) + { // Get a windows handle to std input stream - HANDLE handle = ::GetStdHandle( STD_INPUT_HANDLE ); + HANDLE handle = ::GetStdHandle(STD_INPUT_HANDLE); DWORD nBytesWaiting = ::_kbhit(); - - // Save the number of bytes to be read so that we can check if input is available to be read + + // Save the number of bytes to be read so that we can check if input is available to be read m_nBytesToBeRead = nBytesWaiting; // Return state of whether bytes are waiting or not @@ -201,36 +205,37 @@ bool CMICmnStreamStdinWindows::InputAvailableConsoleWin( bool & vwbAvail ) } #endif // #if defined( _MSC_VER ) - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Determine if stdin has any characters present in its buffer. -// Type: Method. -// Args: vwbAvail - (W) True = There is chars available, false = nothing there. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Determine if stdin has any characters present in its buffer. +// Type: Method. +// Args: vwbAvail - (W) True = There is chars available, false = nothing there. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdinWindows::InputAvailableApplication( bool & vwbAvail ) +bool +CMICmnStreamStdinWindows::InputAvailableApplication(bool &vwbAvail) { - #if defined( _MSC_VER ) - if( m_nBytesToBeRead == 0 ) - { +#if defined(_MSC_VER) + if (m_nBytesToBeRead == 0) + { // Get a windows handle to std input stream - HANDLE handle = ::GetStdHandle( STD_INPUT_HANDLE ); + HANDLE handle = ::GetStdHandle(STD_INPUT_HANDLE); DWORD nBytesWaiting = 0; // Ask how many bytes are available - if( ::PeekNamedPipe( handle, nullptr, 0, nullptr, &nBytesWaiting, nullptr ) == FALSE ) + if (::PeekNamedPipe(handle, nullptr, 0, nullptr, &nBytesWaiting, nullptr) == FALSE) { // This can occur when the client i.e. Eclipse closes the stdin stream 'cause it deems its work is finished // for that debug session. May be we should be handling SIGKILL somehow? - const CMIUtilString osErrMsg( CMIUtilSystemWindows().GetOSLastError().StripCRAll() ); - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_STDIN_ERR_CHKING_BYTE_AVAILABLE ), osErrMsg.c_str() ) ); + const CMIUtilString osErrMsg(CMIUtilSystemWindows().GetOSLastError().StripCRAll()); + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_STDIN_ERR_CHKING_BYTE_AVAILABLE), osErrMsg.c_str())); return MIstatus::failure; } - + // Save the number of bytes to be read so that we can check if input is available to be read m_nBytesToBeRead = nBytesWaiting; @@ -239,41 +244,42 @@ bool CMICmnStreamStdinWindows::InputAvailableApplication( bool & vwbAvail ) } #endif // #if defined( _MSC_VER ) - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Wait on new line of data from stdin stream (completed by '\n' or '\r'). -// Type: Method. -// Args: vwErrMsg - (W) Empty string ok or error description. -// Return: MIchar * - text buffer pointer or NULL on failure. -// Throws: None. +// Details: Wait on new line of data from stdin stream (completed by '\n' or '\r'). +// Type: Method. +// Args: vwErrMsg - (W) Empty string ok or error description. +// Return: MIchar * - text buffer pointer or NULL on failure. +// Throws: None. //-- -const MIchar * CMICmnStreamStdinWindows::ReadLine( CMIUtilString & vwErrMsg ) +const MIchar * +CMICmnStreamStdinWindows::ReadLine(CMIUtilString &vwErrMsg) { - vwErrMsg.clear(); - - // Read user input - const MIchar * pText = ::fgets( &m_pCmdBuffer[ 0 ], m_constBufferSize, stdin ); - if( pText == nullptr ) - { - if( ::ferror( m_pStdin ) != 0 ) - vwErrMsg = ::strerror( errno ); - return nullptr; - } + vwErrMsg.clear(); + + // Read user input + const MIchar *pText = ::fgets(&m_pCmdBuffer[0], m_constBufferSize, stdin); + if (pText == nullptr) + { + if (::ferror(m_pStdin) != 0) + vwErrMsg = ::strerror(errno); + return nullptr; + } // Subtract the number of bytes read so that we can check if input is available to be read - m_nBytesToBeRead = m_nBytesToBeRead - ::strlen( pText ); - - // Strip off new line characters - for( MIchar * pI = m_pCmdBuffer; *pI != '\0'; pI++ ) - { - if( (*pI == '\n') || (*pI == '\r') ) - { - *pI = '\0'; - break; - } - } - - return pText; -} \ No newline at end of file + m_nBytesToBeRead = m_nBytesToBeRead - ::strlen(pText); + + // Strip off new line characters + for (MIchar *pI = m_pCmdBuffer; *pI != '\0'; pI++) + { + if ((*pI == '\n') || (*pI == '\r')) + { + *pI = '\0'; + break; + } + } + + return pText; +} diff --git a/tools/lldb-mi/MICmnStreamStdinWindows.h b/tools/lldb-mi/MICmnStreamStdinWindows.h index 8feff8babfbf..40e4e8546fe4 100644 --- a/tools/lldb-mi/MICmnStreamStdinWindows.h +++ b/tools/lldb-mi/MICmnStreamStdinWindows.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilStreamStdin.h +// File: MIUtilStreamStdin.h // -// Overview: CMICmnStreamStdinWindows interface. +// Overview: CMICmnStreamStdinWindows interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -27,55 +27,53 @@ #include "MIUtilSingletonBase.h" //++ ============================================================================ -// Details: MI common code class. Specific OS stdin handling implementation. -// CMICmnStreamStdin instance is set with stdin handler before using the -// the stream. An instance of this class must be set up and ready to give -// to the CMICmnStreamStdin before it initialises other CMICmnStreamStdin -// will give an error. -// Gotchas: None. -// Authors: Illya Rudkin 16/06/2014. -// Changes: None. +// Details: MI common code class. Specific OS stdin handling implementation. +// CMICmnStreamStdin instance is set with stdin handler before using the +// the stream. An instance of this class must be set up and ready to give +// to the CMICmnStreamStdin before it initialises other CMICmnStreamStdin +// will give an error. +// Gotchas: None. +// Authors: Illya Rudkin 16/06/2014. +// Changes: None. //-- -class CMICmnStreamStdinWindows -: public CMICmnBase -, public CMICmnStreamStdin::IOSStdinHandler -, public MI::ISingleton< CMICmnStreamStdinWindows > +class CMICmnStreamStdinWindows : public CMICmnBase, + public CMICmnStreamStdin::IOSStdinHandler, + public MI::ISingleton { - // Give singleton access to private constructors - friend MI::ISingleton< CMICmnStreamStdinWindows >; + // Give singleton access to private constructors + friend MI::ISingleton; -// Methods: -public: - bool Initialize( void ); - bool Shutdown( void ); + // Methods: + public: + bool Initialize(void); + bool Shutdown(void); -// Overridden: -public: - // From CMICmnStreamStdin::IOSpecificReadStreamStdin - virtual bool InputAvailable( bool & vwbAvail ); - virtual const MIchar * ReadLine( CMIUtilString & vwErrMsg ); - -// Methods: -private: - /* ctor */ CMICmnStreamStdinWindows( void ); - /* ctor */ CMICmnStreamStdinWindows( const CMICmnStreamStdinWindows & ); - void operator=( const CMICmnStreamStdinWindows & ); - // - bool InputAvailableConsoleWin( bool & vwbAvail ); - bool InputAvailableApplication( bool & vwbAvail ); - -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMICmnStreamStdinWindows( void ); + // Overridden: + public: + // From CMICmnStreamStdin::IOSpecificReadStreamStdin + virtual bool InputAvailable(bool &vwbAvail); + virtual const MIchar *ReadLine(CMIUtilString &vwErrMsg); -// Attributes: -private: - const MIuint m_constBufferSize; - FILE * m_pStdin; - MIchar * m_pCmdBuffer; - MIchar * m_pStdinBuffer; // Custom buffer to store std input - MIuint m_nBytesToBeRead; // Checks that ::fgets() is holding on to data while ::PeekNamedPipe() returns nothing which causes a problem - bool m_bRunningInConsoleWin; // True = The application is being run in a Windows command line prompt window, false = by other means -}; + // Methods: + private: + /* ctor */ CMICmnStreamStdinWindows(void); + /* ctor */ CMICmnStreamStdinWindows(const CMICmnStreamStdinWindows &); + void operator=(const CMICmnStreamStdinWindows &); + // + bool InputAvailableConsoleWin(bool &vwbAvail); + bool InputAvailableApplication(bool &vwbAvail); + + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMICmnStreamStdinWindows(void); + // Attributes: + private: + const MIuint m_constBufferSize; + FILE *m_pStdin; + MIchar *m_pCmdBuffer; + MIchar *m_pStdinBuffer; // Custom buffer to store std input + MIuint m_nBytesToBeRead; // Checks that ::fgets() is holding on to data while ::PeekNamedPipe() returns nothing which causes a problem + bool m_bRunningInConsoleWin; // True = The application is being run in a Windows command line prompt window, false = by other means +}; diff --git a/tools/lldb-mi/MICmnStreamStdout.cpp b/tools/lldb-mi/MICmnStreamStdout.cpp index 0532820eb790..e32d4fca2446 100644 --- a/tools/lldb-mi/MICmnStreamStdout.cpp +++ b/tools/lldb-mi/MICmnStreamStdout.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilStreamcStdout.cpp +// File: MIUtilStreamcStdout.cpp // -// Overview: CMICmnStreamStdout implementation. +// Overview: CMICmnStreamStdout implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -26,205 +26,213 @@ #include "MIDriver.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStdout constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnStreamStdout constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnStreamStdout::CMICmnStreamStdout( void ) +CMICmnStreamStdout::CMICmnStreamStdout(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStdout destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnStreamStdout destructor. +// Type: Overridable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnStreamStdout::~CMICmnStreamStdout( void ) +CMICmnStreamStdout::~CMICmnStreamStdout(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this Stdout stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialize resources for *this Stdout stream. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdout::Initialize( void ) +bool +CMICmnStreamStdout::Initialize(void) { - m_clientUsageRefCnt++; + m_clientUsageRefCnt++; - if( m_bInitialized ) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; + + bool bOk = MIstatus::success; - bool bOk = MIstatus::success; - #ifdef _MSC_VER - // Debugging / I/O issues with client. - // This is only required on Windows if you do not use ::flush(stdout). MI uses - // ::flush(stdout) - // It trys to ensure the process attached to the stdout steam gets ALL the data. - //::setbuf( stdout, NULL ); +// Debugging / I/O issues with client. +// This is only required on Windows if you do not use ::flush(stdout). MI uses +// ::flush(stdout) +// It trys to ensure the process attached to the stdout steam gets ALL the data. +//::setbuf( stdout, NULL ); #endif // _MSC_VER - - m_bInitialized = bOk; - return MIstatus::success; + m_bInitialized = bOk; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this Stdout stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Release resources for *this Stdout stream. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdout::Shutdown( void ) +bool +CMICmnStreamStdout::Shutdown(void) { - if( --m_clientUsageRefCnt > 0 ) - return MIstatus::success; - - if( !m_bInitialized ) - return MIstatus::success; + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - ClrErrorDescription(); + if (!m_bInitialized) + return MIstatus::success; - m_bInitialized = false; + ClrErrorDescription(); - return MIstatus::success; -} + m_bInitialized = false; + + return MIstatus::success; +} //++ ------------------------------------------------------------------------------------ -// Details: Write an MI format type response to stdout. The text data does not need to -// include a carrage line return as this is added to the text. The function also -// then passes the text data into the CMICmnLog logger. -// Type: Method. -// Args: vText - (R) MI formatted text. -// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Write an MI format type response to stdout. The text data does not need to +// include a carrage line return as this is added to the text. The function also +// then passes the text data into the CMICmnLog logger. +// Type: Method. +// Args: vText - (R) MI formatted text. +// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdout::WriteMIResponse( const CMIUtilString & vText, const bool vbSendToLog /* = true */ ) +bool +CMICmnStreamStdout::WriteMIResponse(const CMIUtilString &vText, const bool vbSendToLog /* = true */) { - return WritePriv( vText, vText, vbSendToLog ); + return WritePriv(vText, vText, vbSendToLog); } //++ ------------------------------------------------------------------------------------ -// Details: Write text data to stdout. The text data does not need to -// include a carrage line return as this is added to the text. The function also -// then passes the text data into the CMICmnLog logger. -// Type: Method. -// Args: vText - (R) Text data. -// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Write text data to stdout. The text data does not need to +// include a carrage line return as this is added to the text. The function also +// then passes the text data into the CMICmnLog logger. +// Type: Method. +// Args: vText - (R) Text data. +// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdout::Write( const CMIUtilString & vText, const bool vbSendToLog /* = true */ ) +bool +CMICmnStreamStdout::Write(const CMIUtilString &vText, const bool vbSendToLog /* = true */) { - if( vText.length() == 0 ) - return MIstatus::failure; + if (vText.length() == 0) + return MIstatus::failure; - const CMIUtilString strPrefixed( CMIUtilString::Format( "%s: %s", CMIDriver::Instance().GetAppNameShort().c_str(), vText.c_str() ) ); + const CMIUtilString strPrefixed(CMIUtilString::Format("%s: %s", CMIDriver::Instance().GetAppNameShort().c_str(), vText.c_str())); - return WritePriv( strPrefixed, vText, vbSendToLog ); + return WritePriv(strPrefixed, vText, vbSendToLog); } //++ ------------------------------------------------------------------------------------ -// Details: Write text data to stdout. The text data does not need to -// include a carrage line return as this is added to the text. The function also -// then passes the text data into the CMICmnLog logger. -// Type: Method. -// Args: vText - (R) Text data prefixed with MI app's short name. -// vTxtForLogFile - (R) Text data. -// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Write text data to stdout. The text data does not need to +// include a carrage line return as this is added to the text. The function also +// then passes the text data into the CMICmnLog logger. +// Type: Method. +// Args: vText - (R) Text data prefixed with MI app's short name. +// vTxtForLogFile - (R) Text data. +// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdout::WritePriv( const CMIUtilString & vText, const CMIUtilString & vTxtForLogFile, const bool vbSendToLog /* = true */ ) +bool +CMICmnStreamStdout::WritePriv(const CMIUtilString &vText, const CMIUtilString &vTxtForLogFile, const bool vbSendToLog /* = true */) { - if( vText.length() == 0 ) - return MIstatus::failure; - - bool bOk = MIstatus::success; - { - // Grab the stdout thread lock while we print - CMIUtilThreadLock _lock( m_mutex ); - - // Send this text to stdout - const MIuint status = ::fputs( vText.c_str(), stdout ); - if( status == EOF ) - { - const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_STDOUT_ERR_NOT_ALL_DATA_WRITTEN ), vText.c_str() ) ); - SetErrorDescription( errMsg ); - bOk = MIstatus::failure; - } - else - { - ::fprintf( stdout, "\n" ); - ::fflush( stdout ); - } - - // Send this text to the log - if( bOk && vbSendToLog ) - bOk &= m_pLog->WriteLog( vTxtForLogFile ); - } - - return bOk; + if (vText.length() == 0) + return MIstatus::failure; + + bool bOk = MIstatus::success; + { + // Grab the stdout thread lock while we print + CMIUtilThreadLock _lock(m_mutex); + + // Send this text to stdout + const MIint status = ::fputs(vText.c_str(), stdout); + if (status == EOF) + { + const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_STDOUT_ERR_NOT_ALL_DATA_WRITTEN), vText.c_str())); + SetErrorDescription(errMsg); + bOk = MIstatus::failure; + } + else + { + ::fprintf(stdout, "\n"); + ::fflush(stdout); + } + + // Send this text to the log + if (bOk && vbSendToLog) + bOk &= m_pLog->WriteLog(vTxtForLogFile); + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Lock the availability of the stream stdout. Other users of *this stream will -// be stalled until it is available (Unlock()). -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Lock the availability of the stream stdout. Other users of *this stream will +// be stalled until it is available (Unlock()). +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdout::Lock( void ) +bool +CMICmnStreamStdout::Lock(void) { - m_mutex.Lock(); - return MIstatus::success; + m_mutex.Lock(); + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Release a previously locked stdout. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Release a previously locked stdout. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdout::Unlock( void ) +bool +CMICmnStreamStdout::Unlock(void) { - m_mutex.Unlock(); - return MIstatus::success; + m_mutex.Unlock(); + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Take a text data and send to the stdout stream. Also output to the MI Log -// file. -// Type: Static method. -// Args: vrTxt - (R) Text. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Take a text data and send to the stdout stream. Also output to the MI Log +// file. +// Type: Static method. +// Args: vrTxt - (R) Text. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMICmnStreamStdout::TextToStdout( const CMIUtilString & vrTxt ) +bool +CMICmnStreamStdout::TextToStdout(const CMIUtilString &vrTxt) { - const bool bLock = CMICmnStreamStdout::Instance().Lock(); - const bool bOk = bLock && CMICmnStreamStdout::Instance().WriteMIResponse( vrTxt ); - bLock && CMICmnStreamStdout::Instance().Unlock(); - - return bOk; + const bool bLock = CMICmnStreamStdout::Instance().Lock(); + const bool bOk = bLock && CMICmnStreamStdout::Instance().WriteMIResponse(vrTxt); + bLock &&CMICmnStreamStdout::Instance().Unlock(); + + return bOk; } diff --git a/tools/lldb-mi/MICmnStreamStdout.h b/tools/lldb-mi/MICmnStreamStdout.h index 90f50478f06d..677a5c4a1868 100644 --- a/tools/lldb-mi/MICmnStreamStdout.h +++ b/tools/lldb-mi/MICmnStreamStdout.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnStreamStdout.h +// File: MICmnStreamStdout.h // -// Overview: CMICmnStreamStdout interface. +// Overview: CMICmnStreamStdout interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -28,48 +28,46 @@ #include "MIUtilSingletonBase.h" //++ ============================================================================ -// Details: MI common code class. The MI driver requires this object. -// CMICmnStreamStdout sets up and tears downs stdout for the driver. -// -// Singleton class. -// Gotchas: None. -// Authors: Illya Rudkin 12/02/2014. -// Changes: None. +// Details: MI common code class. The MI driver requires this object. +// CMICmnStreamStdout sets up and tears downs stdout for the driver. +// +// Singleton class. +// Gotchas: None. +// Authors: Illya Rudkin 12/02/2014. +// Changes: None. //-- -class CMICmnStreamStdout -: public CMICmnBase -, public MI::ISingleton< CMICmnStreamStdout > +class CMICmnStreamStdout : public CMICmnBase, public MI::ISingleton { - friend class MI::ISingleton< CMICmnStreamStdout >; + friend class MI::ISingleton; + + // Statics: + public: + static bool TextToStdout(const CMIUtilString &vrTxt); -// Statics: -public: - static bool TextToStdout( const CMIUtilString & vrTxt ); + // Methods: + public: + bool Initialize(void); + bool Shutdown(void); + // + bool Lock(void); + bool Unlock(void); + bool Write(const CMIUtilString &vText, const bool vbSendToLog = true); + bool WriteMIResponse(const CMIUtilString &vText, const bool vbSendToLog = true); -// Methods: -public: - bool Initialize( void ); - bool Shutdown( void ); - // - bool Lock( void ); - bool Unlock( void ); - bool Write( const CMIUtilString & vText, const bool vbSendToLog = true ); - bool WriteMIResponse( const CMIUtilString & vText, const bool vbSendToLog = true ); + // Methods: + private: + /* ctor */ CMICmnStreamStdout(void); + /* ctor */ CMICmnStreamStdout(const CMICmnStreamStdout &); + void operator=(const CMICmnStreamStdout &); + // + bool WritePriv(const CMIUtilString &vText, const CMIUtilString &vTxtForLogFile, const bool vbSendToLog = true); -// Methods: -private: - /* ctor */ CMICmnStreamStdout( void ); - /* ctor */ CMICmnStreamStdout( const CMICmnStreamStdout & ); - void operator=( const CMICmnStreamStdout & ); - // - bool WritePriv( const CMIUtilString & vText, const CMIUtilString & vTxtForLogFile, const bool vbSendToLog = true ); - -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMICmnStreamStdout( void ); + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMICmnStreamStdout(void); -// Attributes: -private: - CMIUtilThreadMutex m_mutex; // Mutex object for sync during writing to stream + // Attributes: + private: + CMIUtilThreadMutex m_mutex; // Mutex object for sync during writing to stream }; diff --git a/tools/lldb-mi/MICmnThreadMgrStd.cpp b/tools/lldb-mi/MICmnThreadMgrStd.cpp index 757012a697e0..8fa30125b832 100644 --- a/tools/lldb-mi/MICmnThreadMgrStd.cpp +++ b/tools/lldb-mi/MICmnThreadMgrStd.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnThreadMgr.cpp +// File: MICmnThreadMgr.cpp // -// Overview: CMICmnThreadMgr implementation. +// Overview: CMICmnThreadMgr implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -26,142 +26,146 @@ #include "MIUtilSingletonHelper.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnThreadMgr constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnThreadMgr constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnThreadMgrStd::CMICmnThreadMgrStd( void ) +CMICmnThreadMgrStd::CMICmnThreadMgrStd(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnThreadMgr destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnThreadMgr destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnThreadMgrStd::~CMICmnThreadMgrStd( void ) +CMICmnThreadMgrStd::~CMICmnThreadMgrStd(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialise resources for *this thread manager. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialise resources for *this thread manager. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnThreadMgrStd::Initialize( void ) +bool +CMICmnThreadMgrStd::Initialize(void) { - m_clientUsageRefCnt++; - - if( m_bInitialized ) - return MIstatus::success; - - bool bOk = MIstatus::success; - - ClrErrorDescription(); - CMIUtilString errMsg; - - // Note initialisation order is important here as some resources depend on previous - MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); - MI::ModuleInit< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg ); - - m_bInitialized = bOk; - - if( !bOk ) - { - CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_THREADMGR ), errMsg.c_str() ) ); - SetErrorDescription( strInitError ); - return MIstatus::failure; - } - - return bOk; + m_clientUsageRefCnt++; + + if (m_bInitialized) + return MIstatus::success; + + bool bOk = MIstatus::success; + + ClrErrorDescription(); + CMIUtilString errMsg; + + // Note initialisation order is important here as some resources depend on previous + MI::ModuleInit(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + + m_bInitialized = bOk; + + if (!bOk) + { + CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_THREADMGR), errMsg.c_str())); + SetErrorDescription(strInitError); + return MIstatus::failure; + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this thread manager. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Release resources for *this thread manager. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnThreadMgrStd::Shutdown( void ) +bool +CMICmnThreadMgrStd::Shutdown(void) { - if( --m_clientUsageRefCnt > 0 ) - return MIstatus::success; - - if( !m_bInitialized ) - return MIstatus::success; + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; + + if (!m_bInitialized) + return MIstatus::success; + + m_bInitialized = false; - m_bInitialized = false; + ClrErrorDescription(); - ClrErrorDescription(); + bool bOk = MIstatus::success; + CMIUtilString errMsg; - bool bOk = MIstatus::success; - CMIUtilString errMsg; + // Tidy up + ThreadAllTerminate(); - // Tidy up - ThreadAllTerminate(); - - // Note shutdown order is important here - MI::ModuleShutdown< CMICmnResources >( IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg ); - MI::ModuleShutdown< CMICmnLog > ( IDS_MI_SHTDWN_ERR_LOG , bOk, errMsg ); + // Note shutdown order is important here + MI::ModuleShutdown(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg); - if( !bOk ) - { - SetErrorDescriptionn( MIRSRC( IDS_MI_SHUTDOWN_ERR ), errMsg.c_str() ); - } + if (!bOk) + { + SetErrorDescriptionn(MIRSRC(IDS_MI_SHUTDOWN_ERR), errMsg.c_str()); + } - return bOk; + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Ask the thread manager to kill all threads and wait until they have died -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Ask the thread manager to kill all threads and wait until they have died +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnThreadMgrStd::ThreadAllTerminate( void ) +bool +CMICmnThreadMgrStd::ThreadAllTerminate(void) { - ThreadList_t::const_iterator it = m_threadList.begin(); - for( ; it != m_threadList.end(); ++it ) - { - // If the thread is still running - CMIUtilThreadActiveObjBase * pThread = *it; - if( pThread->ThreadIsActive() ) - { - // Ask this thread to kill itself - pThread->ThreadKill(); - - // Wait for this thread to die - pThread->ThreadJoin(); - } - } - - return MIstatus::success; + ThreadList_t::const_iterator it = m_threadList.begin(); + for (; it != m_threadList.end(); ++it) + { + // If the thread is still running + CMIUtilThreadActiveObjBase *pThread = *it; + if (pThread->ThreadIsActive()) + { + // Ask this thread to kill itself + pThread->ThreadKill(); + + // Wait for this thread to die + pThread->ThreadJoin(); + } + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Add a thread object to *this manager's list of thread objects. The list to -// used to manage thread objects centrally. -// Type: Method. -// Args: vrObj - (R) A thread object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Add a thread object to *this manager's list of thread objects. The list to +// used to manage thread objects centrally. +// Type: Method. +// Args: vrObj - (R) A thread object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnThreadMgrStd::AddThread( const CMIUtilThreadActiveObjBase & vrObj ) +bool +CMICmnThreadMgrStd::AddThread(const CMIUtilThreadActiveObjBase &vrObj) { - m_threadList.push_back( const_cast< CMIUtilThreadActiveObjBase * >( &vrObj ) ); + m_threadList.push_back(const_cast(&vrObj)); - return MIstatus::success; + return MIstatus::success; } diff --git a/tools/lldb-mi/MICmnThreadMgrStd.h b/tools/lldb-mi/MICmnThreadMgrStd.h index f0c157a468af..598c98a9def3 100644 --- a/tools/lldb-mi/MICmnThreadMgrStd.h +++ b/tools/lldb-mi/MICmnThreadMgrStd.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MICmnThreadMgrStd.h +// File: MICmnThreadMgrStd.h // -// Overview: CMICmnThreadMgr interface. +// Overview: CMICmnThreadMgr interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -31,104 +31,108 @@ #include "MIUtilSingletonBase.h" //++ ============================================================================ -// Details: MI's worker thread (active thread) manager. -// The manager creates threads and behalf of clients. Client are -// responsible for their threads and can delete them when necessary. -// This manager will stop and delete all threads on *this manager's -// shutdown. -// Singleton class. -// Gotchas: None. -// Authors: Aidan Dodds 12/03/2014. -// Changes: None. +// Details: MI's worker thread (active thread) manager. +// The manager creates threads and behalf of clients. Client are +// responsible for their threads and can delete them when necessary. +// This manager will stop and delete all threads on *this manager's +// shutdown. +// Singleton class. +// Gotchas: None. +// Authors: Aidan Dodds 12/03/2014. +// Changes: None. //-- -class CMICmnThreadMgrStd -: public CMICmnBase -, public MI::ISingleton< CMICmnThreadMgrStd > +class CMICmnThreadMgrStd : public CMICmnBase, public MI::ISingleton { - friend MI::ISingleton< CMICmnThreadMgrStd >; - -// Methods: -public: - bool Initialize( void ); - bool Shutdown( void ); - bool ThreadAllTerminate( void ); // Ask all threads to stop (caution) - template< typename T > // Ask the thread manager to start and stop threads on our behalf - bool ThreadStart( T & vrwObject ); - -// Typedef: -private: - typedef std::vector< CMIUtilThreadActiveObjBase * > ThreadList_t; - -// Methods: -private: - /* ctor */ CMICmnThreadMgrStd( void ); - /* ctor */ CMICmnThreadMgrStd( const CMICmnThreadMgrStd & ); - void operator=( const CMICmnThreadMgrStd & ); - // - bool AddThread( const CMIUtilThreadActiveObjBase & vrObj ); // Add a thread for monitoring by the threadmanager - -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMICmnThreadMgrStd( void ); - -// Attributes: -private: - CMIUtilThreadMutex m_mutex; - ThreadList_t m_threadList; + friend MI::ISingleton; + + // Methods: + public: + bool Initialize(void); + bool Shutdown(void); + bool + ThreadAllTerminate(void); // Ask all threads to stop (caution) + template // Ask the thread manager to start and stop threads on our behalf + bool ThreadStart(T &vrwObject); + + // Typedef: + private: + typedef std::vector ThreadList_t; + + // Methods: + private: + /* ctor */ CMICmnThreadMgrStd(void); + /* ctor */ CMICmnThreadMgrStd(const CMICmnThreadMgrStd &); + void operator=(const CMICmnThreadMgrStd &); + // + bool + AddThread(const CMIUtilThreadActiveObjBase &vrObj); // Add a thread for monitoring by the threadmanager + + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMICmnThreadMgrStd(void); + + // Attributes: + private: + CMIUtilThreadMutex m_mutex; + ThreadList_t m_threadList; }; //++ ------------------------------------------------------------------------------------ -// Details: Given a thread object start its (worker) thread to do work. The object is -// added to the *this manager for housekeeping and deletion of all thread objects. -// Type: Template method. -// Args: vrwThreadObj - (RW) A CMIUtilThreadActiveObjBase derived object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Given a thread object start its (worker) thread to do work. The object is +// added to the *this manager for housekeeping and deletion of all thread objects. +// Type: Template method. +// Args: vrwThreadObj - (RW) A CMIUtilThreadActiveObjBase derived object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -template< typename T > -bool CMICmnThreadMgrStd::ThreadStart( T & vrwThreadObj ) +template +bool +CMICmnThreadMgrStd::ThreadStart(T &vrwThreadObj) { - bool bOk = MIstatus::success; - - // Grab a reference to the base object type - CMIUtilThreadActiveObjBase & rObj = static_cast< CMIUtilThreadActiveObjBase & >( vrwThreadObj ); - - // Add to the thread managers internal database - bOk &= AddThread( rObj ); - if( !bOk ) - { - const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_THREADMGR_ERR_THREAD_FAIL_CREATE ), vrwThreadObj.ThreadGetName().c_str() ) ); - SetErrorDescription( errMsg ); - return MIstatus::failure; - } - - // Grab a reference on behalf of the caller - bOk &= vrwThreadObj.Acquire(); - if( !bOk ) - { - const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_THREADMGR_ERR_THREAD_FAIL_CREATE ), vrwThreadObj.ThreadGetName().c_str() ) ); - SetErrorDescription( errMsg ); - return MIstatus::failure; - } - - // Thread is already started - // This call must come after the reference count increment - if( vrwThreadObj.ThreadIsActive() ) - { - // Early exit on thread already running condition - return MIstatus::success; - } - - // Start the thread running - bOk &= vrwThreadObj.ThreadExecute(); - if( !bOk ) - { - const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_THREADMGR_ERR_THREAD_FAIL_CREATE ), vrwThreadObj.ThreadGetName().c_str() ) ); - SetErrorDescription( errMsg ); - return MIstatus::failure; - } - - return MIstatus::success; + bool bOk = MIstatus::success; + + // Grab a reference to the base object type + CMIUtilThreadActiveObjBase &rObj = static_cast(vrwThreadObj); + + // Add to the thread managers internal database + bOk &= AddThread(rObj); + if (!bOk) + { + const CMIUtilString errMsg( + CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE), vrwThreadObj.ThreadGetName().c_str())); + SetErrorDescription(errMsg); + return MIstatus::failure; + } + + // Grab a reference on behalf of the caller + bOk &= vrwThreadObj.Acquire(); + if (!bOk) + { + const CMIUtilString errMsg( + CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE), vrwThreadObj.ThreadGetName().c_str())); + SetErrorDescription(errMsg); + return MIstatus::failure; + } + + // Thread is already started + // This call must come after the reference count increment + if (vrwThreadObj.ThreadIsActive()) + { + // Early exit on thread already running condition + return MIstatus::success; + } + + // Start the thread running + bOk &= vrwThreadObj.ThreadExecute(); + if (!bOk) + { + const CMIUtilString errMsg( + CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE), vrwThreadObj.ThreadGetName().c_str())); + SetErrorDescription(errMsg); + return MIstatus::failure; + } + + return MIstatus::success; } diff --git a/tools/lldb-mi/MIDataTypes.h b/tools/lldb-mi/MIDataTypes.h index c7980a8851a3..aced1c66f8d9 100644 --- a/tools/lldb-mi/MIDataTypes.h +++ b/tools/lldb-mi/MIDataTypes.h @@ -8,19 +8,19 @@ //===----------------------------------------------------------------------===// //++ -// File: MIDataTypes.h +// File: MIDataTypes.h // -// Overview: Common global switches, macros, etc. +// Overview: Common global switches, macros, etc. // -// This file contains common data types required by applications -// generally. If supported by the compiler, this file should be -// #include'd as part of the project's PCH (precompiled header). +// This file contains common data types required by applications +// generally. If supported by the compiler, this file should be +// #include'd as part of the project's PCH (precompiled header). // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -31,8 +31,8 @@ // Debugging: #ifdef _DEBUG -#include // C-runtime debugging library (defines _ASSERT). -#endif // _DEBUG +#include // C-runtime debugging library (defines _ASSERT). +#endif // _DEBUG #endif // _WIN32 @@ -42,15 +42,15 @@ // Function return status namespace MIstatus { - const bool success = true; - const bool failure = false; +const bool success = true; +const bool failure = false; } // Use to avoid "unused parameter" compiler warnings: -#define MIunused( x ) (void) x; +#define MIunused(x) (void) x; #ifdef _WIN32 -#define MI_NO_INITIALIZE_VTABLE __declspec( novtable ) +#define MI_NO_INITIALIZE_VTABLE __declspec(novtable) #define MI_FORCE_INLINE __forceinline #else #define MI_NO_INITIALIZE_VTABLE @@ -59,40 +59,40 @@ namespace MIstatus #endif // _WIN32 // Portability issues -#ifdef _WIN64 - typedef unsigned __int64 size_t; - typedef unsigned __int64 PointerToInteger_t; - typedef __int64 MIint; - typedef unsigned __int64 MIuint; +#ifdef _WIN64 +typedef unsigned __int64 size_t; +typedef unsigned __int64 PointerToInteger_t; +typedef __int64 MIint; +typedef unsigned __int64 MIuint; #else - #ifdef _WIN32 - typedef unsigned int size_t; - typedef unsigned int PointerToInteger_t; - typedef int MIint; - typedef unsigned int MIuint; - #else -// typedef long unsigned int size_t; // size_t already defined - typedef unsigned int PointerToInteger_t; - typedef int MIint; - typedef unsigned int MIuint; - - #define MAX_PATH 4096 - #endif // _WIN32 +#ifdef _WIN32 +typedef unsigned int size_t; +typedef unsigned int PointerToInteger_t; +typedef int MIint; +typedef unsigned int MIuint; +#else +// typedef long unsigned int size_t; // size_t already defined +typedef unsigned int PointerToInteger_t; +typedef int MIint; +typedef unsigned int MIuint; + +#define MAX_PATH 4096 +#endif // _WIN32 #endif // _WIN64 //-------------------------------------------------------------------------------------- // Common types: // Fundamentals: -typedef float MIflt; -typedef double MIdbl; -typedef char MIchar; // Defaults to signed char, i.e. MIschar. -typedef signed char MIschar; // Range: -128 to 127. More explicit than using MIchar. -typedef unsigned char MIuchar; // Range: 0 to 255. -typedef long long MIint64; // 64bit signed integer. -typedef unsigned long long MIuint64; // 64bit unsigned integer. - -//using namespace std; // Better to put this or std:: at translation units scope. +typedef float MIflt; +typedef double MIdbl; +typedef char MIchar; // Defaults to signed char, i.e. MIschar. +typedef signed char MIschar; // Range: -128 to 127. More explicit than using MIchar. +typedef unsigned char MIuchar; // Range: 0 to 255. +typedef long long MIint64; // 64bit signed integer. +typedef unsigned long long MIuint64; // 64bit unsigned integer. + +// using namespace std; // Better to put this or std:: at translation units scope. //-------------------------------------------------------------------------------------- // Common routines: diff --git a/tools/lldb-mi/MIDriver.cpp b/tools/lldb-mi/MIDriver.cpp index 759d54a5364d..accde1c7cde7 100644 --- a/tools/lldb-mi/MIDriver.cpp +++ b/tools/lldb-mi/MIDriver.cpp @@ -8,19 +8,19 @@ //===----------------------------------------------------------------------===// //++ -// File: MIDriver.cpp +// File: MIDriver.cpp // -// Overview: CMIDriver implementation. +// Overview: CMIDriver implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third party headers: -#include // va_list, va_start, var_end +#include // va_list, va_start, var_end #include #include @@ -44,1233 +44,1286 @@ // Instantiations: #if _DEBUG - const CMIUtilString CMIDriver::ms_constMIVersion = MIRSRC( IDS_MI_VERSION_DESCRIPTION_DEBUG ); +const CMIUtilString CMIDriver::ms_constMIVersion = MIRSRC(IDS_MI_VERSION_DESCRIPTION_DEBUG); #else - const CMIUtilString CMIDriver::ms_constMIVersion = MIRSRC( IDS_MI_VERSION_DESCRIPTION ); // Matches version in resources file +const CMIUtilString CMIDriver::ms_constMIVersion = MIRSRC(IDS_MI_VERSION_DESCRIPTION); // Matches version in resources file #endif // _DEBUG -const CMIUtilString CMIDriver::ms_constAppNameShort( MIRSRC( IDS_MI_APPNAME_SHORT ) ); -const CMIUtilString CMIDriver::ms_constAppNameLong( MIRSRC( IDS_MI_APPNAME_LONG ) ); +const CMIUtilString CMIDriver::ms_constAppNameShort(MIRSRC(IDS_MI_APPNAME_SHORT)); +const CMIUtilString CMIDriver::ms_constAppNameLong(MIRSRC(IDS_MI_APPNAME_LONG)); //++ ------------------------------------------------------------------------------------ -// Details: CMIDriver constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIDriver constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIDriver::CMIDriver( void ) -: m_bFallThruToOtherDriverEnabled( false ) -, m_bDriverIsExiting( false ) -, m_handleMainThread( 0 ) -, m_rStdin( CMICmnStreamStdin::Instance() ) -, m_rLldbDebugger( CMICmnLLDBDebugger::Instance() ) -, m_rStdOut( CMICmnStreamStdout::Instance() ) -, m_eCurrentDriverState( eDriverState_NotRunning ) -, m_bHaveExecutableFileNamePathOnCmdLine( false ) -, m_bDriverDebuggingArgExecutable( false ) +CMIDriver::CMIDriver(void) + : m_bFallThruToOtherDriverEnabled(false) + , m_bDriverIsExiting(false) + , m_handleMainThread(0) + , m_rStdin(CMICmnStreamStdin::Instance()) + , m_rLldbDebugger(CMICmnLLDBDebugger::Instance()) + , m_rStdOut(CMICmnStreamStdout::Instance()) + , m_eCurrentDriverState(eDriverState_NotRunning) + , m_bHaveExecutableFileNamePathOnCmdLine(false) + , m_bDriverDebuggingArgExecutable(false) { } //++ ------------------------------------------------------------------------------------ -// Details: CMIDriver destructor. -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIDriver destructor. +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIDriver::~CMIDriver( void ) +CMIDriver::~CMIDriver(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Set whether *this driver (the parent) is enabled to pass a command to its -// fall through (child) driver to interpret the command and do work instead -// (if *this driver decides it can't hanled the command). -// Type: Method. -// Args: vbYes - (R) True = yes fall through, false = do not pass on command. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Set whether *this driver (the parent) is enabled to pass a command to its +// fall through (child) driver to interpret the command and do work instead +// (if *this driver decides it can't hanled the command). +// Type: Method. +// Args: vbYes - (R) True = yes fall through, false = do not pass on command. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::SetEnableFallThru( const bool vbYes ) +bool +CMIDriver::SetEnableFallThru(const bool vbYes) { - m_bFallThruToOtherDriverEnabled = vbYes; - return MIstatus::success; + m_bFallThruToOtherDriverEnabled = vbYes; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Get whether *this driver (the parent) is enabled to pass a command to its -// fall through (child) driver to interpret the command and do work instead -// (if *this driver decides it can't hanled the command). -// Type: Method. -// Args: None. -// Return: bool - True = yes fall through, false = do not pass on command. -// Throws: None. +// Details: Get whether *this driver (the parent) is enabled to pass a command to its +// fall through (child) driver to interpret the command and do work instead +// (if *this driver decides it can't hanled the command). +// Type: Method. +// Args: None. +// Return: bool - True = yes fall through, false = do not pass on command. +// Throws: None. //-- -bool CMIDriver::GetEnableFallThru( void ) const +bool +CMIDriver::GetEnableFallThru(void) const { - return m_bFallThruToOtherDriverEnabled; + return m_bFallThruToOtherDriverEnabled; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve MI's application name of itself. -// Type: Method. -// Args: None. -// Return: CMIUtilString & - Text description. -// Throws: None. +// Details: Retrieve MI's application name of itself. +// Type: Method. +// Args: None. +// Return: CMIUtilString & - Text description. +// Throws: None. //-- -const CMIUtilString & CMIDriver::GetAppNameShort( void ) const +const CMIUtilString & +CMIDriver::GetAppNameShort(void) const { - return ms_constAppNameShort; + return ms_constAppNameShort; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve MI's application name of itself. -// Type: Method. -// Args: None. -// Return: CMIUtilString & - Text description. -// Throws: None. +// Details: Retrieve MI's application name of itself. +// Type: Method. +// Args: None. +// Return: CMIUtilString & - Text description. +// Throws: None. //-- -const CMIUtilString & CMIDriver::GetAppNameLong( void ) const +const CMIUtilString & +CMIDriver::GetAppNameLong(void) const { - return ms_constAppNameLong; + return ms_constAppNameLong; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve MI's version description of itself. -// Type: Method. -// Args: None. -// Return: CMIUtilString & - Text description. -// Throws: None. +// Details: Retrieve MI's version description of itself. +// Type: Method. +// Args: None. +// Return: CMIUtilString & - Text description. +// Throws: None. //-- -const CMIUtilString & CMIDriver::GetVersionDescription( void ) const +const CMIUtilString & +CMIDriver::GetVersionDescription(void) const { - return ms_constMIVersion; + return ms_constMIVersion; } //++ ------------------------------------------------------------------------------------ -// Details: Initialize setup *this driver ready for use. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialize setup *this driver ready for use. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::Initialize( void ) +bool +CMIDriver::Initialize(void) { - m_eCurrentDriverState = eDriverState_Initialising; - m_clientUsageRefCnt++; + m_eCurrentDriverState = eDriverState_Initialising; + m_clientUsageRefCnt++; - ClrErrorDescription(); + ClrErrorDescription(); - if( m_bInitialized ) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - bool bOk = MIstatus::success; - CMIUtilString errMsg; + bool bOk = MIstatus::success; + CMIUtilString errMsg; - // Initialize all of the modules we depend on - MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); - MI::ModuleInit< CMICmnStreamStdout >( IDS_MI_INIT_ERR_STREAMSTDOUT , bOk, errMsg ); - MI::ModuleInit< CMICmnStreamStderr >( IDS_MI_INIT_ERR_STREAMSTDERR , bOk, errMsg ); - MI::ModuleInit< CMICmnResources > ( IDS_MI_INIT_ERR_RESOURCES , bOk, errMsg ); - MI::ModuleInit< CMICmnThreadMgrStd >( IDS_MI_INIT_ERR_THREADMANAGER, bOk, errMsg ); - MI::ModuleInit< CMICmnStreamStdin > ( IDS_MI_INIT_ERR_STREAMSTDIN , bOk, errMsg ); - MI::ModuleInit< CMICmdMgr > ( IDS_MI_INIT_ERR_CMDMGR , bOk, errMsg ); - bOk &= m_rLldbDebugger.SetDriver( *this ); - MI::ModuleInit< CMICmnLLDBDebugger >( IDS_MI_INIT_ERR_LLDBDEBUGGER , bOk, errMsg ); + // Initialize all of the modules we depend on + MI::ModuleInit(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_STREAMSTDOUT, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_STREAMSTDERR, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_THREADMANAGER, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_STREAMSTDIN, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_CMDMGR, bOk, errMsg); + bOk &= m_rLldbDebugger.SetDriver(*this); + MI::ModuleInit(IDS_MI_INIT_ERR_LLDBDEBUGGER, bOk, errMsg); #if MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER - CMIDriverMgr & rDrvMgr = CMIDriverMgr::Instance(); - bOk = bOk && rDrvMgr.RegisterDriver( *g_driver, "LLDB driver" ); // Will be pass thru driver - if( bOk ) - { - bOk = SetEnableFallThru( false ); // This is intentional at this time - yet to be fully implemented - bOk = bOk && SetDriverToFallThruTo( *g_driver ); - CMIUtilString strOtherDrvErrMsg; - if( bOk && GetEnableFallThru() && !g_driver->MISetup( strOtherDrvErrMsg ) ) - { - bOk = false; - errMsg = CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_FALLTHRUDRIVER ), strOtherDrvErrMsg.c_str() ); - } - } + CMIDriverMgr &rDrvMgr = CMIDriverMgr::Instance(); + bOk = bOk && rDrvMgr.RegisterDriver(*g_driver, "LLDB driver"); // Will be pass thru driver + if (bOk) + { + bOk = SetEnableFallThru(false); // This is intentional at this time - yet to be fully implemented + bOk = bOk && SetDriverToFallThruTo(*g_driver); + CMIUtilString strOtherDrvErrMsg; + if (bOk && GetEnableFallThru() && !g_driver->MISetup(strOtherDrvErrMsg)) + { + bOk = false; + errMsg = CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_FALLTHRUDRIVER), strOtherDrvErrMsg.c_str()); + } + } #endif // MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER - m_bExitApp = false; - - m_bInitialized = bOk; + m_bExitApp = false; - if( !bOk ) - { - const CMIUtilString msg = CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_DRIVER ), errMsg.c_str() ); - SetErrorDescription( msg ); - return MIstatus::failure; - } + m_bInitialized = bOk; - m_eCurrentDriverState = eDriverState_RunningNotDebugging; - - return bOk; + if (!bOk) + { + const CMIUtilString msg = CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_DRIVER), errMsg.c_str()); + SetErrorDescription(msg); + return MIstatus::failure; + } + + m_eCurrentDriverState = eDriverState_RunningNotDebugging; + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Unbind detach or release resources used by *this driver. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Unbind detach or release resources used by *this driver. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::Shutdown( void ) +bool +CMIDriver::Shutdown(void) { - if( --m_clientUsageRefCnt > 0 ) - return MIstatus::success; - - if( !m_bInitialized ) - return MIstatus::success; - - m_eCurrentDriverState = eDriverState_ShuttingDown; - - ClrErrorDescription(); - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Shutdown all of the modules we depend on - MI::ModuleShutdown< CMICmnLLDBDebugger >( IDS_MI_INIT_ERR_LLDBDEBUGGER , bOk, errMsg ); - MI::ModuleShutdown< CMICmdMgr > ( IDS_MI_INIT_ERR_CMDMGR , bOk, errMsg ); - MI::ModuleShutdown< CMICmnStreamStdin > ( IDS_MI_INIT_ERR_STREAMSTDIN , bOk, errMsg ); - MI::ModuleShutdown< CMICmnThreadMgrStd >( IDS_MI_INIT_ERR_THREADMANAGER, bOk, errMsg ); - MI::ModuleShutdown< CMICmnResources > ( IDS_MI_INIT_ERR_RESOURCES , bOk, errMsg ); - MI::ModuleShutdown< CMICmnStreamStderr >( IDS_MI_INIT_ERR_STREAMSTDERR , bOk, errMsg ); - MI::ModuleShutdown< CMICmnStreamStdout >( IDS_MI_INIT_ERR_STREAMSTDOUT , bOk, errMsg ); - MI::ModuleShutdown< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); - - if( !bOk ) - { - SetErrorDescriptionn( MIRSRC( IDS_MI_SHUTDOWN_ERR ), errMsg.c_str() ); - } - - m_eCurrentDriverState = eDriverState_NotRunning; - - return bOk; + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; + + if (!m_bInitialized) + return MIstatus::success; + + m_eCurrentDriverState = eDriverState_ShuttingDown; + + ClrErrorDescription(); + + bool bOk = MIstatus::success; + CMIUtilString errMsg; + + // Shutdown all of the modules we depend on + MI::ModuleShutdown(IDS_MI_INIT_ERR_LLDBDEBUGGER, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_INIT_ERR_CMDMGR, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_INIT_ERR_STREAMSTDIN, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_INIT_ERR_THREADMANAGER, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_INIT_ERR_STREAMSTDERR, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_INIT_ERR_STREAMSTDOUT, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + + if (!bOk) + { + SetErrorDescriptionn(MIRSRC(IDS_MI_SHUTDOWN_ERR), errMsg.c_str()); + } + + m_eCurrentDriverState = eDriverState_NotRunning; + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Work function. Client (the driver's user) is able to append their own message -// in to the MI's Log trace file. -// Type: Method. -// Args: vMessage - (R) Client's text message. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Work function. Client (the driver's user) is able to append their own message +// in to the MI's Log trace file. +// Type: Method. +// Args: vMessage - (R) Client's text message. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::WriteMessageToLog( const CMIUtilString & vMessage ) +bool +CMIDriver::WriteMessageToLog(const CMIUtilString &vMessage) { - CMIUtilString msg; - msg = CMIUtilString::Format( MIRSRC( IDS_MI_CLIENT_MSG ), vMessage.c_str() ); - return m_pLog->Write( msg, CMICmnLog::eLogVerbosity_ClientMsg ); + CMIUtilString msg; + msg = CMIUtilString::Format(MIRSRC(IDS_MI_CLIENT_MSG), vMessage.c_str()); + return m_pLog->Write(msg, CMICmnLog::eLogVerbosity_ClientMsg); } //++ ------------------------------------------------------------------------------------ // Details: CDriverMgr calls *this driver initialize setup ready for use. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::DoInitialize( void ) +bool +CMIDriver::DoInitialize(void) { - return CMIDriver::Instance().Initialize(); + return CMIDriver::Instance().Initialize(); } //++ ------------------------------------------------------------------------------------ -// Details: CDriverMgr calls *this driver to unbind detach or release resources used by -// *this driver. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: CDriverMgr calls *this driver to unbind detach or release resources used by +// *this driver. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::DoShutdown( void ) +bool +CMIDriver::DoShutdown(void) { - return CMIDriver::Instance().Shutdown(); + return CMIDriver::Instance().Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the name for *this driver. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString & - Driver name. -// Throws: None. +// Details: Retrieve the name for *this driver. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString & - Driver name. +// Throws: None. //-- -const CMIUtilString & CMIDriver::GetName( void ) const +const CMIUtilString & +CMIDriver::GetName(void) const { - const CMIUtilString & rName = GetAppNameLong(); - const CMIUtilString & rVsn = GetVersionDescription(); - static CMIUtilString strName = CMIUtilString::Format( "%s %s", rName.c_str(), rVsn.c_str() ); - - return strName; + const CMIUtilString &rName = GetAppNameLong(); + const CMIUtilString &rVsn = GetVersionDescription(); + static CMIUtilString strName = CMIUtilString::Format("%s %s", rName.c_str(), rVsn.c_str()); + + return strName; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve *this driver's last error condition. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString - Text description. -// Throws: None. +// Details: Retrieve *this driver's last error condition. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString - Text description. +// Throws: None. //-- -CMIUtilString CMIDriver::GetError( void ) const +CMIUtilString +CMIDriver::GetError(void) const { - return GetErrorDescription(); + return GetErrorDescription(); } //++ ------------------------------------------------------------------------------------ -// Details: Call *this driver to resize the console window. -// Type: Overridden. -// Args: vTermWidth - (R) New window column size. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Call *this driver to resize the console window. +// Type: Overridden. +// Args: vTermWidth - (R) New window column size. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -void CMIDriver::DoResizeWindow( const uint32_t vTermWidth ) +void +CMIDriver::DoResizeWindow(const uint32_t vTermWidth) { - GetTheDebugger().SetTerminalWidth( vTermWidth ); + GetTheDebugger().SetTerminalWidth(vTermWidth); } //++ ------------------------------------------------------------------------------------ -// Details: Call *this driver to return it's debugger. -// Type: Overridden. -// Args: None. -// Return: lldb::SBDebugger & - LLDB debugger object reference. -// Throws: None. +// Details: Call *this driver to return it's debugger. +// Type: Overridden. +// Args: None. +// Return: lldb::SBDebugger & - LLDB debugger object reference. +// Throws: None. //-- -lldb::SBDebugger & CMIDriver::GetTheDebugger( void ) +lldb::SBDebugger & +CMIDriver::GetTheDebugger(void) { - return m_rLldbDebugger.GetTheDebugger(); + return m_rLldbDebugger.GetTheDebugger(); } //++ ------------------------------------------------------------------------------------ -// Details: Specify another driver *this driver can call should this driver not be able -// to handle the client data input. DoFallThruToAnotherDriver() makes the call. -// Type: Overridden. -// Args: vrOtherDriver - (R) Reference to another driver object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Specify another driver *this driver can call should this driver not be able +// to handle the client data input. DoFallThruToAnotherDriver() makes the call. +// Type: Overridden. +// Args: vrOtherDriver - (R) Reference to another driver object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::SetDriverToFallThruTo( const CMIDriverBase & vrOtherDriver ) +bool +CMIDriver::SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver) { - m_pDriverFallThru = const_cast< CMIDriverBase * >( &vrOtherDriver ); + m_pDriverFallThru = const_cast(&vrOtherDriver); - return m_pDriverFallThru->SetDriverParent( *this ); + return m_pDriverFallThru->SetDriverParent(*this); } //++ ------------------------------------------------------------------------------------ -// Details: Proxy function CMIDriverMgr IDriver interface implementation. *this driver's -// implementation called from here to match the existing function name of the -// original LLDb driver class (the extra indirection is not necessarily required). -// Check the arguments that were passed to this program to make sure they are -// valid and to get their argument values (if any). -// Type: Overridden. -// Args: argc - (R) An integer that contains the count of arguments that follow in -// argv. The argc parameter is always greater than or equal to 1. -// argv - (R) An array of null-terminated strings representing command-line -// arguments entered by the user of the program. By convention, -// argv[0] is the command with which the program is invoked. -// vpStdOut - (R) Pointer to a standard output stream. -// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s), -// version information only. -// False = Continue to work, start debugger i.e. Command -// interpreter. -// Return: lldb::SBError - LLDB current error status. -// Throws: None. +// Details: Proxy function CMIDriverMgr IDriver interface implementation. *this driver's +// implementation called from here to match the existing function name of the +// original LLDb driver class (the extra indirection is not necessarily required). +// Check the arguments that were passed to this program to make sure they are +// valid and to get their argument values (if any). +// Type: Overridden. +// Args: argc - (R) An integer that contains the count of arguments that follow in +// argv. The argc parameter is always greater than or equal to 1. +// argv - (R) An array of null-terminated strings representing command-line +// arguments entered by the user of the program. By convention, +// argv[0] is the command with which the program is invoked. +// vpStdOut - (R) Pointer to a standard output stream. +// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s), +// version information only. +// False = Continue to work, start debugger i.e. Command +// interpreter. +// Return: lldb::SBError - LLDB current error status. +// Throws: None. //-- -lldb::SBError CMIDriver::DoParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting ) +lldb::SBError +CMIDriver::DoParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting) { - return ParseArgs( argc, argv, vpStdOut, vwbExiting ); + return ParseArgs(argc, argv, vpStdOut, vwbExiting); } //++ ------------------------------------------------------------------------------------ -// Details: Check the arguments that were passed to this program to make sure they are -// valid and to get their argument values (if any). The following are options -// that are only handled by *this driver: -// --executable -// The application's options --interpreter and --executable in code act very similar. -// The --executable is necessary to differentiate whither the MI Driver is being -// using by a client i.e. Eclipse or from the command line. Eclipse issues the option -// --interpreter and also passes additional arguments which can be interpreted as an -// executable if called from the command line. Using --executable tells the MI -// Driver is being called the command line and that the executable argument is indeed -// a specified executable an so actions commands to set up the executable for a -// debug session. Using --interpreter on the commnd line does not action additional -// commands to initialise a debug session and so be able to launch the process. -// Type: Overridden. -// Args: argc - (R) An integer that contains the count of arguments that follow in -// argv. The argc parameter is always greater than or equal to 1. -// argv - (R) An array of null-terminated strings representing command-line -// arguments entered by the user of the program. By convention, -// argv[0] is the command with which the program is invoked. -// vpStdOut - (R) Pointer to a standard output stream. -// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s), -// version information only. -// False = Continue to work, start debugger i.e. Command -// interpreter. -// Return: lldb::SBError - LLDB current error status. -// Throws: None. +// Details: Check the arguments that were passed to this program to make sure they are +// valid and to get their argument values (if any). The following are options +// that are only handled by *this driver: +// --executable +// The application's options --interpreter and --executable in code act very similar. +// The --executable is necessary to differentiate whither the MI Driver is being +// using by a client i.e. Eclipse or from the command line. Eclipse issues the option +// --interpreter and also passes additional arguments which can be interpreted as an +// executable if called from the command line. Using --executable tells the MI +// Driver is being called the command line and that the executable argument is indeed +// a specified executable an so actions commands to set up the executable for a +// debug session. Using --interpreter on the commnd line does not action additional +// commands to initialise a debug session and so be able to launch the process. +// Type: Overridden. +// Args: argc - (R) An integer that contains the count of arguments that follow in +// argv. The argc parameter is always greater than or equal to 1. +// argv - (R) An array of null-terminated strings representing command-line +// arguments entered by the user of the program. By convention, +// argv[0] is the command with which the program is invoked. +// vpStdOut - (R) Pointer to a standard output stream. +// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s), +// version information only. +// False = Continue to work, start debugger i.e. Command +// interpreter. +// Return: lldb::SBError - LLDB current error status. +// Throws: None. //-- -lldb::SBError CMIDriver::ParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting ) +lldb::SBError +CMIDriver::ParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting) { - lldb::SBError errStatus; - const bool bHaveArgs( argc >= 2 ); - - // *** Add any args handled here to GetHelpOnCmdLineArgOptions() *** - - // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING - // Look for the command line options - bool bHaveExecutableFileNamePath = false; - bool bHaveExecutableLongOption = false; - - if( bHaveArgs ) - { - // Search right to left to look for the executable - for( MIint i = argc - 1; i > 0; i-- ) - { - const CMIUtilString strArg( argv[ i ] ); - const CMICmdArgValFile argFile; - if( argFile.IsFilePath( strArg ) || - CMICmdArgValString( true, false, true ).IsStringArg( strArg )) - { - bHaveExecutableFileNamePath = true; - m_strCmdLineArgExecuteableFileNamePath = argFile.GetFileNamePath( strArg ); - m_bHaveExecutableFileNamePathOnCmdLine = true; - } - // This argument is also check for in CMIDriverMgr::ParseArgs() - if( 0 == strArg.compare( "--executable" ) ) // Used to specify that there is executable argument also on the command line - { // See fn description. - bHaveExecutableLongOption = true; - } - } - } - - if( bHaveExecutableFileNamePath && bHaveExecutableLongOption ) - { - // CODETAG_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION + lldb::SBError errStatus; + const bool bHaveArgs(argc >= 2); + + // *** Add any args handled here to GetHelpOnCmdLineArgOptions() *** + + // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING + // Look for the command line options + bool bHaveExecutableFileNamePath = false; + bool bHaveExecutableLongOption = false; + + if (bHaveArgs) + { + // Search right to left to look for the executable + for (MIint i = argc - 1; i > 0; i--) + { + const CMIUtilString strArg(argv[i]); + const CMICmdArgValFile argFile; + if (argFile.IsFilePath(strArg) || CMICmdArgValString(true, false, true).IsStringArg(strArg)) + { + bHaveExecutableFileNamePath = true; + m_strCmdLineArgExecuteableFileNamePath = argFile.GetFileNamePath(strArg); + m_bHaveExecutableFileNamePathOnCmdLine = true; + } + // This argument is also check for in CMIDriverMgr::ParseArgs() + if (0 == strArg.compare("--executable")) // Used to specify that there is executable argument also on the command line + { // See fn description. + bHaveExecutableLongOption = true; + } + } + } + + if (bHaveExecutableFileNamePath && bHaveExecutableLongOption) + { +// CODETAG_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION #if MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION - SetDriverDebuggingArgExecutable(); + SetDriverDebuggingArgExecutable(); #else - vwbExiting = true; - errStatus.SetErrorString( MIRSRC( IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL ) ); + vwbExiting = true; + errStatus.SetErrorString(MIRSRC(IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL)); #endif // MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION - } + } - return errStatus; + return errStatus; } //++ ------------------------------------------------------------------------------------ -// Details: A client can ask if *this driver is GDB/MI compatible. -// Type: Overridden. -// Args: None. -// Return: True - GBD/MI compatible LLDB front end. -// False - Not GBD/MI compatible LLDB front end. -// Throws: None. +// Details: A client can ask if *this driver is GDB/MI compatible. +// Type: Overridden. +// Args: None. +// Return: True - GBD/MI compatible LLDB front end. +// False - Not GBD/MI compatible LLDB front end. +// Throws: None. //-- -bool CMIDriver::GetDriverIsGDBMICompatibleDriver( void ) const +bool +CMIDriver::GetDriverIsGDBMICompatibleDriver(void) const { - return true; + return true; } //++ ------------------------------------------------------------------------------------ -// Details: Callback function for monitoring stream stdin object. Part of the visitor -// pattern. -// This function is called by the CMICmnStreamStdin::CThreadStdin -// "stdin monitor" thread (ID). -// Type: Overridden. -// Args: vStdInBuffer - (R) Copy of the current stdin line data. -// vrbYesExit - (RW) True = yes exit stdin monitoring, false = continue monitor. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Callback function for monitoring stream stdin object. Part of the visitor +// pattern. +// This function is called by the CMICmnStreamStdin::CThreadStdin +// "stdin monitor" thread (ID). +// Type: Overridden. +// Args: vStdInBuffer - (R) Copy of the current stdin line data. +// vrbYesExit - (RW) True = yes exit stdin monitoring, false = continue monitor. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::ReadLine( const CMIUtilString & vStdInBuffer, bool & vrwbYesExit ) +bool +CMIDriver::ReadLine(const CMIUtilString &vStdInBuffer, bool &vrwbYesExit) { - // For debugging. Update prompt show stdin is working - //printf( "%s\n", vStdInBuffer.c_str() ); - //fflush( stdout ); + // For debugging. Update prompt show stdin is working + // printf( "%s\n", vStdInBuffer.c_str() ); + // fflush( stdout ); - // Special case look for the quit command here so stop monitoring stdin stream - // So we do not go back to fgetc() and wait and hang thread on exit - if( vStdInBuffer == "quit" ) - vrwbYesExit = true; + // Special case look for the quit command here so stop monitoring stdin stream + // So we do not go back to fgetc() and wait and hang thread on exit + if (vStdInBuffer == "quit") + vrwbYesExit = true; - // 1. Put new line in the queue container by stdin monitor thread - // 2. Then *this driver calls ReadStdinLineQueue() when ready to read the queue in its - // own thread - const bool bOk = QueueMICommand( vStdInBuffer ); + // 1. Put new line in the queue container by stdin monitor thread + // 2. Then *this driver calls ReadStdinLineQueue() when ready to read the queue in its + // own thread + const bool bOk = QueueMICommand(vStdInBuffer); - // Check to see if the *this driver is shutting down (exit application) - if( !vrwbYesExit ) - vrwbYesExit = m_bDriverIsExiting; + // Check to see if the *this driver is shutting down (exit application) + if (!vrwbYesExit) + vrwbYesExit = m_bDriverIsExiting; - return bOk; + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Start worker threads for the driver. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Start worker threads for the driver. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::StartWorkerThreads( void ) +bool +CMIDriver::StartWorkerThreads(void) { - bool bOk = MIstatus::success; - - // Grab the thread manager - CMICmnThreadMgrStd & rThreadMgr = CMICmnThreadMgrStd::Instance(); - - // Start the stdin thread - bOk &= m_rStdin.SetVisitor( *this ); - if( bOk && !rThreadMgr.ThreadStart< CMICmnStreamStdin >( m_rStdin )) - { - const CMIUtilString errMsg = CMIUtilString::Format( MIRSRC( IDS_THREADMGR_ERR_THREAD_FAIL_CREATE ), CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str() ); - SetErrorDescriptionn( errMsg ); - return MIstatus::failure; - } - - // Start the event polling thread - if( bOk && !rThreadMgr.ThreadStart< CMICmnLLDBDebugger >( m_rLldbDebugger ) ) - { - const CMIUtilString errMsg = CMIUtilString::Format( MIRSRC( IDS_THREADMGR_ERR_THREAD_FAIL_CREATE ), CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str() ); - SetErrorDescriptionn( errMsg ); - return MIstatus::failure; - } - - return bOk; + bool bOk = MIstatus::success; + + // Grab the thread manager + CMICmnThreadMgrStd &rThreadMgr = CMICmnThreadMgrStd::Instance(); + + // Start the stdin thread + bOk &= m_rStdin.SetVisitor(*this); + if (bOk && !rThreadMgr.ThreadStart(m_rStdin)) + { + const CMIUtilString errMsg = CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE), + CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str()); + SetErrorDescriptionn(errMsg); + return MIstatus::failure; + } + + // Start the event polling thread + if (bOk && !rThreadMgr.ThreadStart(m_rLldbDebugger)) + { + const CMIUtilString errMsg = CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE), + CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str()); + SetErrorDescriptionn(errMsg); + return MIstatus::failure; + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Stop worker threads for the driver. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Stop worker threads for the driver. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::StopWorkerThreads( void ) +bool +CMIDriver::StopWorkerThreads(void) { - CMICmnThreadMgrStd & rThreadMgr = CMICmnThreadMgrStd::Instance(); - return rThreadMgr.ThreadAllTerminate(); + CMICmnThreadMgrStd &rThreadMgr = CMICmnThreadMgrStd::Instance(); + return rThreadMgr.ThreadAllTerminate(); } //++ ------------------------------------------------------------------------------------ -// Details: Call this function puts *this driver to work. -// This function is used by the application's main thread. -// Type: Overridden. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Call this function puts *this driver to work. +// This function is used by the application's main thread. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::DoMainLoop( void ) +bool +CMIDriver::DoMainLoop(void) { - if( !InitClientIDEToMIDriver() ) // Init Eclipse IDE - { - SetErrorDescriptionn( MIRSRC( IDS_MI_INIT_ERR_CLIENT_USING_DRIVER ) ); - return MIstatus::failure; - } - - if( !StartWorkerThreads() ) - return MIstatus::failure; - - // App is not quitting currently - m_bExitApp = false; - - // CODETAG_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION + if (!InitClientIDEToMIDriver()) // Init Eclipse IDE + { + SetErrorDescriptionn(MIRSRC(IDS_MI_INIT_ERR_CLIENT_USING_DRIVER)); + return MIstatus::failure; + } + + if (!StartWorkerThreads()) + return MIstatus::failure; + + // App is not quitting currently + m_bExitApp = false; + +// CODETAG_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION #if MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION - if( HaveExecutableFileNamePathOnCmdLine() ) - { - if( !LocalDebugSessionStartupInjectCommands() ) - { - SetErrorDescription( MIRSRC( IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION ) ); - return MIstatus::failure; - } - } + if (HaveExecutableFileNamePathOnCmdLine()) + { + if (!LocalDebugSessionStartupInjectCommands()) + { + SetErrorDescription(MIRSRC(IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION)); + return MIstatus::failure; + } + } #endif // MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION - // While the app is active - while( !m_bExitApp ) - { - // Poll stdin queue and dispatch - if( !ReadStdinLineQueue() ) - { - // Something went wrong - break; - } - } + // While the app is active + while (!m_bExitApp) + { + // Poll stdin queue and dispatch + if (!ReadStdinLineQueue()) + { + // Something went wrong + break; + } + } - // Signal that the application is shutting down - DoAppQuit(); + // Signal that the application is shutting down + DoAppQuit(); - // Close and wait for the workers to stop - StopWorkerThreads(); + // Close and wait for the workers to stop + StopWorkerThreads(); - // Ensure that a new line is sent as the last act of the dying driver - m_rStdOut.WriteMIResponse( "\n", false ); + // Ensure that a new line is sent as the last act of the dying driver + m_rStdOut.WriteMIResponse("\n", false); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: *this driver sits and waits for input to the stdin line queue shared by *this -// driver and the stdin monitor thread, it queues, *this reads, interprets and -// reacts. -// This function is used by the application's main thread. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: *this driver sits and waits for input to the stdin line queue shared by *this +// driver and the stdin monitor thread, it queues, *this reads, interprets and +// reacts. +// This function is used by the application's main thread. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::ReadStdinLineQueue( void ) +bool +CMIDriver::ReadStdinLineQueue(void) { - // True when queue contains input - bool bHaveInput = false; - - // Stores the current input line - CMIUtilString lineText; - { - // Lock while we access the queue - CMIUtilThreadLock lock( m_threadMutex ); - if( !m_queueStdinLine.empty() ) - { - lineText = m_queueStdinLine.front(); - m_queueStdinLine.pop(); - bHaveInput = !lineText.empty(); - } - } - - // Process while we have input - if( bHaveInput ) - { - if( lineText == "quit" ) - { - // We want to be exiting when receiving a quit command - m_bExitApp = true; - return MIstatus::success; - } - - // Process the command - const bool bOk = InterpretCommand( lineText ); - - // Draw prompt if desired - if( bOk && m_rStdin.GetEnablePrompt() ) - m_rStdOut.WriteMIResponse( m_rStdin.GetPrompt() ); - - // Input has been processed - bHaveInput = false; - } - else - { - // Give resources back to the OS - const std::chrono::milliseconds time( 1 ); - std::this_thread::sleep_for( time ); - } - - return MIstatus::success; + // True when queue contains input + bool bHaveInput = false; + + // Stores the current input line + CMIUtilString lineText; + { + // Lock while we access the queue + CMIUtilThreadLock lock(m_threadMutex); + if (!m_queueStdinLine.empty()) + { + lineText = m_queueStdinLine.front(); + m_queueStdinLine.pop(); + bHaveInput = !lineText.empty(); + } + } + + // Process while we have input + if (bHaveInput) + { + if (lineText == "quit") + { + // We want to be exiting when receiving a quit command + m_bExitApp = true; + return MIstatus::success; + } + + // Process the command + const bool bOk = InterpretCommand(lineText); + + // Draw prompt if desired + if (bOk && m_rStdin.GetEnablePrompt()) + m_rStdOut.WriteMIResponse(m_rStdin.GetPrompt()); + + // Input has been processed + bHaveInput = false; + } + else + { + // Give resources back to the OS + const std::chrono::milliseconds time(1); + std::this_thread::sleep_for(time); + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Set things in motion, set state etc that brings *this driver (and the -// application) to a tidy shutdown. -// This function is used by the application's main thread. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Set things in motion, set state etc that brings *this driver (and the +// application) to a tidy shutdown. +// This function is used by the application's main thread. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::DoAppQuit( void ) +bool +CMIDriver::DoAppQuit(void) { - bool bYesQuit = true; + bool bYesQuit = true; - // Shutdown stuff, ready app for exit - { - CMIUtilThreadLock lock( m_threadMutex ); - m_bDriverIsExiting = true; - } + // Shutdown stuff, ready app for exit + { + CMIUtilThreadLock lock(m_threadMutex); + m_bDriverIsExiting = true; + } - return bYesQuit; + return bYesQuit; } //++ ------------------------------------------------------------------------------------ -// Details: *this driver passes text commands to a fall through driver is it does not -// understand them (the LLDB driver). -// This function is used by the application's main thread. -// Type: Method. -// Args: vTextLine - (R) Text data representing a possible command. -// vwbCmdYesValid - (W) True = Command valid, false = command not handled. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: *this driver passes text commands to a fall through driver is it does not +// understand them (the LLDB driver). +// This function is used by the application's main thread. +// Type: Method. +// Args: vTextLine - (R) Text data representing a possible command. +// vwbCmdYesValid - (W) True = Command valid, false = command not handled. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::InterpretCommandFallThruDriver( const CMIUtilString & vTextLine, bool & vwbCmdYesValid ) +bool +CMIDriver::InterpretCommandFallThruDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid) { - MIunused( vTextLine ); - MIunused( vwbCmdYesValid ); - - // ToDo: Implement when less urgent work to be done or decide remove as not required - //bool bOk = MIstatus::success; - //bool bCmdNotUnderstood = true; - //if( bCmdNotUnderstood && GetEnableFallThru() ) - //{ - // CMIUtilString errMsg; - // bOk = DoFallThruToAnotherDriver( vStdInBuffer, errMsg ); - // if( !bOk ) - // { - // errMsg = errMsg.StripCREndOfLine(); - // errMsg = errMsg.StripCRAll(); - // const CMIDriverBase * pOtherDriver = GetDriverToFallThruTo(); - // const MIchar * pName = pOtherDriver->GetDriverName().c_str(); - // const MIchar * pId = pOtherDriver->GetDriverId().c_str(); - // const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR ), pName, pId, errMsg.c_str() ) ); - // m_pLog->WriteMsg( msg ); - // } - //} - // - //vwbCmdYesValid = bOk; - //CMIUtilString strNot; - //if( vwbCmdYesValid) - // strNot = CMIUtilString::Format( "%s ", MIRSRC( IDS_WORD_NOT ) ); - //const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_FALLTHRU_DRIVER_CMD_RECEIVED ), vTextLine.c_str(), strNot.c_str() ) ); - //m_pLog->WriteLog( msg ); - - return MIstatus::success; + MIunused(vTextLine); + MIunused(vwbCmdYesValid); + + // ToDo: Implement when less urgent work to be done or decide remove as not required + // bool bOk = MIstatus::success; + // bool bCmdNotUnderstood = true; + // if( bCmdNotUnderstood && GetEnableFallThru() ) + //{ + // CMIUtilString errMsg; + // bOk = DoFallThruToAnotherDriver( vStdInBuffer, errMsg ); + // if( !bOk ) + // { + // errMsg = errMsg.StripCREndOfLine(); + // errMsg = errMsg.StripCRAll(); + // const CMIDriverBase * pOtherDriver = GetDriverToFallThruTo(); + // const MIchar * pName = pOtherDriver->GetDriverName().c_str(); + // const MIchar * pId = pOtherDriver->GetDriverId().c_str(); + // const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR ), pName, pId, errMsg.c_str() ) + //); + // m_pLog->WriteMsg( msg ); + // } + //} + // + // vwbCmdYesValid = bOk; + // CMIUtilString strNot; + // if( vwbCmdYesValid) + // strNot = CMIUtilString::Format( "%s ", MIRSRC( IDS_WORD_NOT ) ); + // const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_FALLTHRU_DRIVER_CMD_RECEIVED ), vTextLine.c_str(), strNot.c_str() ) ); + // m_pLog->WriteLog( msg ); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the name for *this driver. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString & - Driver name. -// Throws: None. +// Details: Retrieve the name for *this driver. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString & - Driver name. +// Throws: None. //-- -const CMIUtilString & CMIDriver::GetDriverName( void ) const +const CMIUtilString & +CMIDriver::GetDriverName(void) const { - return GetName(); + return GetName(); } //++ ------------------------------------------------------------------------------------ -// Details: Get the unique ID for *this driver. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString & - Text description. -// Throws: None. +// Details: Get the unique ID for *this driver. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString & - Text description. +// Throws: None. //-- -const CMIUtilString & CMIDriver::GetDriverId( void ) const +const CMIUtilString & +CMIDriver::GetDriverId(void) const { - return GetId(); + return GetId(); } //++ ------------------------------------------------------------------------------------ -// Details: This function allows *this driver to call on another driver to perform work -// should this driver not be able to handle the client data input. -// SetDriverToFallThruTo() specifies the fall through to driver. -// Check the error message if the function returns a failure. -// Type: Overridden. -// Args: vCmd - (R) Command instruction to interpret. -// vwErrMsg - (W) Error description on command failing. -// Return: MIstatus::success - Command succeeded. -// MIstatus::failure - Command failed. -// Throws: None. +// Details: This function allows *this driver to call on another driver to perform work +// should this driver not be able to handle the client data input. +// SetDriverToFallThruTo() specifies the fall through to driver. +// Check the error message if the function returns a failure. +// Type: Overridden. +// Args: vCmd - (R) Command instruction to interpret. +// vwErrMsg - (W) Error description on command failing. +// Return: MIstatus::success - Command succeeded. +// MIstatus::failure - Command failed. +// Throws: None. //-- -bool CMIDriver::DoFallThruToAnotherDriver( const CMIUtilString & vCmd, CMIUtilString & vwErrMsg ) +bool +CMIDriver::DoFallThruToAnotherDriver(const CMIUtilString &vCmd, CMIUtilString &vwErrMsg) { - bool bOk = MIstatus::success; + bool bOk = MIstatus::success; - CMIDriverBase * pOtherDriver = GetDriverToFallThruTo(); - if( pOtherDriver == nullptr ) - return bOk; + CMIDriverBase *pOtherDriver = GetDriverToFallThruTo(); + if (pOtherDriver == nullptr) + return bOk; - return pOtherDriver->DoFallThruToAnotherDriver( vCmd, vwErrMsg ); + return pOtherDriver->DoFallThruToAnotherDriver(vCmd, vwErrMsg); } //++ ------------------------------------------------------------------------------------ -// Details: *this driver provides a file stream to other drivers on which *this driver -// write's out to and they read as expected input. *this driver is passing -// through commands to the (child) pass through assigned driver. -// Type: Overrdidden. -// Args: None. -// Return: FILE * - Pointer to stream. -// Throws: None. +// Details: *this driver provides a file stream to other drivers on which *this driver +// write's out to and they read as expected input. *this driver is passing +// through commands to the (child) pass through assigned driver. +// Type: Overrdidden. +// Args: None. +// Return: FILE * - Pointer to stream. +// Throws: None. //-- -FILE * CMIDriver::GetStdin( void ) const +FILE * +CMIDriver::GetStdin(void) const { - // Note this fn is called on CMIDriverMgr register driver so stream has to be - // available before *this driver has been initialized! Flaw? + // Note this fn is called on CMIDriverMgr register driver so stream has to be + // available before *this driver has been initialized! Flaw? - // This very likely to change later to a stream that the pass thru driver - // will read and we write to give it 'input' - return stdin; + // This very likely to change later to a stream that the pass thru driver + // will read and we write to give it 'input' + return stdin; } //++ ------------------------------------------------------------------------------------ -// Details: *this driver provides a file stream to other pass through assigned drivers -// so they know what to write to. -// Type: Overidden. -// Args: None. -// Return: FILE * - Pointer to stream. -// Throws: None. +// Details: *this driver provides a file stream to other pass through assigned drivers +// so they know what to write to. +// Type: Overidden. +// Args: None. +// Return: FILE * - Pointer to stream. +// Throws: None. //-- -FILE * CMIDriver::GetStdout( void ) const +FILE * +CMIDriver::GetStdout(void) const { - // Note this fn is called on CMIDriverMgr register driver so stream has to be - // available before *this driver has been initialized! Flaw? + // Note this fn is called on CMIDriverMgr register driver so stream has to be + // available before *this driver has been initialized! Flaw? - // Do not want to pass through driver to write to stdout - return NULL; + // Do not want to pass through driver to write to stdout + return NULL; } //++ ------------------------------------------------------------------------------------ -// Details: *this driver provides a error file stream to other pass through assigned drivers -// so they know what to write to. -// Type: Overidden. -// Args: None. -// Return: FILE * - Pointer to stream. -// Throws: None. +// Details: *this driver provides a error file stream to other pass through assigned drivers +// so they know what to write to. +// Type: Overidden. +// Args: None. +// Return: FILE * - Pointer to stream. +// Throws: None. //-- -FILE * CMIDriver::GetStderr( void ) const +FILE * +CMIDriver::GetStderr(void) const { - // Note this fn is called on CMIDriverMgr register driver so stream has to be - // available before *this driver has been initialized! Flaw? + // Note this fn is called on CMIDriverMgr register driver so stream has to be + // available before *this driver has been initialized! Flaw? - // This very likely to change later to a stream that the pass thru driver - // will write to and *this driver reads from to pass on the CMICmnLog object - return stderr; + // This very likely to change later to a stream that the pass thru driver + // will write to and *this driver reads from to pass on the CMICmnLog object + return stderr; } //++ ------------------------------------------------------------------------------------ -// Details: Set a unique ID for *this driver. It cannot be empty. -// Type: Overridden. -// Args: vId - (R) Text description. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Set a unique ID for *this driver. It cannot be empty. +// Type: Overridden. +// Args: vId - (R) Text description. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::SetId( const CMIUtilString & vId ) +bool +CMIDriver::SetId(const CMIUtilString &vId) { - if( vId.empty() ) - { - SetErrorDescriptionn( MIRSRC( IDS_DRIVER_ERR_ID_INVALID ), GetName().c_str(), vId.c_str() ); - return MIstatus::failure; - } - - m_strDriverId = vId; - return MIstatus::success; + if (vId.empty()) + { + SetErrorDescriptionn(MIRSRC(IDS_DRIVER_ERR_ID_INVALID), GetName().c_str(), vId.c_str()); + return MIstatus::failure; + } + + m_strDriverId = vId; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Get the unique ID for *this driver. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString & - Text description. -// Throws: None. +// Details: Get the unique ID for *this driver. +// Type: Overridden. +// Args: None. +// Return: CMIUtilString & - Text description. +// Throws: None. //-- -const CMIUtilString & CMIDriver::GetId( void ) const +const CMIUtilString & +CMIDriver::GetId(void) const { - return m_strDriverId; + return m_strDriverId; } //++ ------------------------------------------------------------------------------------ -// Details: Inject a command into the command processing system to be interpreted as a -// command read from stdin. The text representing the command is also written -// out to stdout as the command did not come from via stdin. -// Type: Method. -// Args: vMICmd - (R) Text data representing a possible command. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Inject a command into the command processing system to be interpreted as a +// command read from stdin. The text representing the command is also written +// out to stdout as the command did not come from via stdin. +// Type: Method. +// Args: vMICmd - (R) Text data representing a possible command. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::InjectMICommand( const CMIUtilString & vMICmd ) +bool +CMIDriver::InjectMICommand(const CMIUtilString &vMICmd) { - const bool bOk = m_rStdOut.WriteMIResponse( vMICmd ); + const bool bOk = m_rStdOut.WriteMIResponse(vMICmd); - return bOk && QueueMICommand( vMICmd ); + return bOk && QueueMICommand(vMICmd); } //++ ------------------------------------------------------------------------------------ -// Details: Add a new command candidate to the command queue to be processed by the -// command system. -// Type: Method. -// Args: vMICmd - (R) Text data representing a possible command. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Add a new command candidate to the command queue to be processed by the +// command system. +// Type: Method. +// Args: vMICmd - (R) Text data representing a possible command. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::QueueMICommand( const CMIUtilString & vMICmd ) +bool +CMIDriver::QueueMICommand(const CMIUtilString &vMICmd) { - CMIUtilThreadLock lock( m_threadMutex ); - m_queueStdinLine.push( vMICmd ); - - return MIstatus::success; + CMIUtilThreadLock lock(m_threadMutex); + m_queueStdinLine.push(vMICmd); + + return MIstatus::success; } - + //++ ------------------------------------------------------------------------------------ -// Details: Interpret the text data and match against current commands to see if there -// is a match. If a match then the command is issued and actioned on. The -// text data if not understood by *this driver is past on to the Fall Thru -// driver. -// This function is used by the application's main thread. -// Type: Method. -// Args: vTextLine - (R) Text data representing a possible command. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Interpret the text data and match against current commands to see if there +// is a match. If a match then the command is issued and actioned on. The +// text data if not understood by *this driver is past on to the Fall Thru +// driver. +// This function is used by the application's main thread. +// Type: Method. +// Args: vTextLine - (R) Text data representing a possible command. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::InterpretCommand( const CMIUtilString & vTextLine ) +bool +CMIDriver::InterpretCommand(const CMIUtilString &vTextLine) { - bool bCmdYesValid = false; - bool bOk = InterpretCommandThisDriver( vTextLine, bCmdYesValid ); - if( bOk && !bCmdYesValid ) - bOk = InterpretCommandFallThruDriver( vTextLine, bCmdYesValid ); + bool bCmdYesValid = false; + bool bOk = InterpretCommandThisDriver(vTextLine, bCmdYesValid); + if (bOk && !bCmdYesValid) + bOk = InterpretCommandFallThruDriver(vTextLine, bCmdYesValid); - return bOk; + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Interpret the text data and match against current commands to see if there -// is a match. If a match then the command is issued and actioned on. If a -// command cannot be found to match then vwbCmdYesValid is set to false and -// nothing else is done here. -// This function is used by the application's main thread. -// Type: Method. -// Args: vTextLine - (R) Text data representing a possible command. -// vwbCmdYesValid - (W) True = Command invalid, false = command acted on. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Interpret the text data and match against current commands to see if there +// is a match. If a match then the command is issued and actioned on. If a +// command cannot be found to match then vwbCmdYesValid is set to false and +// nothing else is done here. +// This function is used by the application's main thread. +// Type: Method. +// Args: vTextLine - (R) Text data representing a possible command. +// vwbCmdYesValid - (W) True = Command invalid, false = command acted on. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::InterpretCommandThisDriver( const CMIUtilString & vTextLine, bool & vwbCmdYesValid ) +bool +CMIDriver::InterpretCommandThisDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid) { - vwbCmdYesValid = false; - - bool bCmdNotInCmdFactor = false; - SMICmdData cmdData; - CMICmdMgr & rCmdMgr = CMICmdMgr::Instance(); - if( !rCmdMgr.CmdInterpret( vTextLine, vwbCmdYesValid, bCmdNotInCmdFactor, cmdData ) ) - return MIstatus::failure; - - if( vwbCmdYesValid ) - { - // For debugging only - //m_pLog->WriteLog( cmdData.strMiCmdAll.c_str() ); - - return ExecuteCommand( cmdData ); - } - - // Check for escape character, may be cursor control characters - // This code is not necessary for application operation, just want to keep tabs on what - // is been given to the driver to try and intepret. - if( vTextLine.at( 0 ) == 27 ) - { - CMIUtilString logInput( MIRSRC( IDS_STDIN_INPUT_CTRL_CHARS ) ); - for( MIuint i = 0; i < vTextLine.length(); i++ ) - { - logInput += CMIUtilString::Format( "%d ", vTextLine.at( i ) ); - } - m_pLog->WriteLog( logInput ); - return MIstatus::success; - } - - // Write to the Log that a 'command' was not valid. - // Report back to the MI client via MI result record. - CMIUtilString strNotInCmdFactory; - if( bCmdNotInCmdFactor ) - strNotInCmdFactory = CMIUtilString::Format( MIRSRC( IDS_DRIVER_CMD_NOT_IN_FACTORY ), cmdData.strMiCmd.c_str() ); - const CMIUtilString strNot( CMIUtilString::Format( "%s ", MIRSRC( IDS_WORD_NOT ) ) ); - const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_CMD_RECEIVED ), vTextLine.c_str(), strNot.c_str(), strNotInCmdFactory.c_str() ) ); - const CMICmnMIValueConst vconst = CMICmnMIValueConst( msg ); - const CMICmnMIValueResult valueResult( "msg", vconst ); - const CMICmnMIResultRecord miResultRecord( cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, valueResult ); - m_rStdOut.WriteMIResponse( miResultRecord.GetString() ); - - // Proceed to wait for or execute next command - return MIstatus::success; + vwbCmdYesValid = false; + + bool bCmdNotInCmdFactor = false; + SMICmdData cmdData; + CMICmdMgr &rCmdMgr = CMICmdMgr::Instance(); + if (!rCmdMgr.CmdInterpret(vTextLine, vwbCmdYesValid, bCmdNotInCmdFactor, cmdData)) + return MIstatus::failure; + + if (vwbCmdYesValid) + { + // For debugging only + // m_pLog->WriteLog( cmdData.strMiCmdAll.c_str() ); + + return ExecuteCommand(cmdData); + } + + // Check for escape character, may be cursor control characters + // This code is not necessary for application operation, just want to keep tabs on what + // is been given to the driver to try and intepret. + if (vTextLine.at(0) == 27) + { + CMIUtilString logInput(MIRSRC(IDS_STDIN_INPUT_CTRL_CHARS)); + for (MIuint i = 0; i < vTextLine.length(); i++) + { + logInput += CMIUtilString::Format("%d ", vTextLine.at(i)); + } + m_pLog->WriteLog(logInput); + return MIstatus::success; + } + + // Write to the Log that a 'command' was not valid. + // Report back to the MI client via MI result record. + CMIUtilString strNotInCmdFactory; + if (bCmdNotInCmdFactor) + strNotInCmdFactory = CMIUtilString::Format(MIRSRC(IDS_DRIVER_CMD_NOT_IN_FACTORY), cmdData.strMiCmd.c_str()); + const CMIUtilString strNot(CMIUtilString::Format("%s ", MIRSRC(IDS_WORD_NOT))); + const CMIUtilString msg( + CMIUtilString::Format(MIRSRC(IDS_DRIVER_CMD_RECEIVED), vTextLine.c_str(), strNot.c_str(), strNotInCmdFactory.c_str())); + const CMICmnMIValueConst vconst = CMICmnMIValueConst(msg); + const CMICmnMIValueResult valueResult("msg", vconst); + const CMICmnMIResultRecord miResultRecord(cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, valueResult); + m_rStdOut.WriteMIResponse(miResultRecord.GetString()); + + // Proceed to wait for or execute next command + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Having previously had the potential command validated and found valid now -// get the command executed. -// This function is used by the application's main thread. -// Type: Method. -// Args: vCmdData - (RW) Command meta data. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Having previously had the potential command validated and found valid now +// get the command executed. +// This function is used by the application's main thread. +// Type: Method. +// Args: vCmdData - (RW) Command meta data. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriver::ExecuteCommand( const SMICmdData & vCmdData ) +bool +CMIDriver::ExecuteCommand(const SMICmdData &vCmdData) { - CMICmdMgr & rCmdMgr = CMICmdMgr::Instance(); - return rCmdMgr.CmdExecute( vCmdData ); + CMICmdMgr &rCmdMgr = CMICmdMgr::Instance(); + return rCmdMgr.CmdExecute(vCmdData); } //++ ------------------------------------------------------------------------------------ -// Details: Set the MI Driver's exit application flag. The application checks this flag -// after every stdin line is read so the exit may not be instantaneous. -// If vbForceExit is false the MI Driver queries its state and determines if is -// should exit or continue operating depending on that running state. -// This is related to the running state of the MI driver. -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: Set the MI Driver's exit application flag. The application checks this flag +// after every stdin line is read so the exit may not be instantaneous. +// If vbForceExit is false the MI Driver queries its state and determines if is +// should exit or continue operating depending on that running state. +// This is related to the running state of the MI driver. +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMIDriver::SetExitApplicationFlag( const bool vbForceExit ) +void +CMIDriver::SetExitApplicationFlag(const bool vbForceExit) { - if( vbForceExit ) - { - CMIUtilThreadLock lock( m_threadMutex ); - m_bExitApp = true; - return; - } - - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - // Did we receive a SIGINT from the client during a running debug program, if - // so then SIGINT is not to be taken as meaning kill the MI driver application - // but halt the inferior program being debugged instead - if( m_eCurrentDriverState == eDriverState_RunningDebugging ) - { - InjectMICommand( "-exec-interrupt" ); - return; - } - - m_bExitApp = true; + if (vbForceExit) + { + CMIUtilThreadLock lock(m_threadMutex); + m_bExitApp = true; + m_rStdin.OnExitHandler(); + return; + } + + // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM + // Did we receive a SIGINT from the client during a running debug program, if + // so then SIGINT is not to be taken as meaning kill the MI driver application + // but halt the inferior program being debugged instead + if (m_eCurrentDriverState == eDriverState_RunningDebugging) + { + InjectMICommand("-exec-interrupt"); + return; + } + + m_bExitApp = true; + m_rStdin.OnExitHandler(); } //++ ------------------------------------------------------------------------------------ -// Details: Get the MI Driver's exit exit application flag. -// This is related to the running state of the MI driver. -// Type: Method. -// Args: None. -// Return: bool - True = MI Driver is shutting down, false = MI driver is running. -// Throws: None. +// Details: Get the MI Driver's exit exit application flag. +// This is related to the running state of the MI driver. +// Type: Method. +// Args: None. +// Return: bool - True = MI Driver is shutting down, false = MI driver is running. +// Throws: None. //-- -bool CMIDriver::GetExitApplicationFlag( void ) const +bool +CMIDriver::GetExitApplicationFlag(void) const { - return m_bExitApp; + return m_bExitApp; } //++ ------------------------------------------------------------------------------------ -// Details: Get the current running state of the MI Driver. -// Type: Method. -// Args: None. -// Return: DriverState_e - The current running state of the application. -// Throws: None. +// Details: Get the current running state of the MI Driver. +// Type: Method. +// Args: None. +// Return: DriverState_e - The current running state of the application. +// Throws: None. //-- -CMIDriver::DriverState_e CMIDriver::GetCurrentDriverState( void ) const +CMIDriver::DriverState_e +CMIDriver::GetCurrentDriverState(void) const { - return m_eCurrentDriverState; + return m_eCurrentDriverState; } //++ ------------------------------------------------------------------------------------ -// Details: Set the current running state of the MI Driver to running and currently not in -// a debug session. -// Type: Method. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Return: DriverState_e - The current running state of the application. -// Throws: None. +// Details: Set the current running state of the MI Driver to running and currently not in +// a debug session. +// Type: Method. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Return: DriverState_e - The current running state of the application. +// Throws: None. //-- -bool CMIDriver::SetDriverStateRunningNotDebugging( void ) +bool +CMIDriver::SetDriverStateRunningNotDebugging(void) { - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - - if( m_eCurrentDriverState == eDriverState_RunningNotDebugging ) - return MIstatus::success; - - // Driver cannot be in the following states to set eDriverState_RunningNotDebugging - switch( m_eCurrentDriverState ) - { - case eDriverState_NotRunning: - case eDriverState_Initialising: - case eDriverState_ShuttingDown: - { - SetErrorDescription( MIRSRC( IDS_DRIVER_ERR_DRIVER_STATE_ERROR ) ); - return MIstatus::failure; - } - case eDriverState_RunningDebugging: - case eDriverState_RunningNotDebugging: - break; - case eDriverState_count: - default: - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CODE_ERR_INVALID_ENUMERATION_VALUE ), "SetDriverStateRunningNotDebugging()" ) ); - return MIstatus::failure; - } - - // Driver must be in this state to set eDriverState_RunningNotDebugging - if( m_eCurrentDriverState != eDriverState_RunningDebugging ) - { - SetErrorDescription( MIRSRC( IDS_DRIVER_ERR_DRIVER_STATE_ERROR ) ); - return MIstatus::failure; - } - - m_eCurrentDriverState = eDriverState_RunningNotDebugging; - - return MIstatus::success; + // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM + + if (m_eCurrentDriverState == eDriverState_RunningNotDebugging) + return MIstatus::success; + + // Driver cannot be in the following states to set eDriverState_RunningNotDebugging + switch (m_eCurrentDriverState) + { + case eDriverState_NotRunning: + case eDriverState_Initialising: + case eDriverState_ShuttingDown: + { + SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)); + return MIstatus::failure; + } + case eDriverState_RunningDebugging: + case eDriverState_RunningNotDebugging: + break; + case eDriverState_count: + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_CODE_ERR_INVALID_ENUMERATION_VALUE), "SetDriverStateRunningNotDebugging()")); + return MIstatus::failure; + } + + // Driver must be in this state to set eDriverState_RunningNotDebugging + if (m_eCurrentDriverState != eDriverState_RunningDebugging) + { + SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)); + return MIstatus::failure; + } + + m_eCurrentDriverState = eDriverState_RunningNotDebugging; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Set the current running state of the MI Driver to running and currently not in -// a debug session. The driver's state must in the state running and in a -// debug session to set this new state. -// Type: Method. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Return: DriverState_e - The current running state of the application. -// Throws: None. +// Details: Set the current running state of the MI Driver to running and currently not in +// a debug session. The driver's state must in the state running and in a +// debug session to set this new state. +// Type: Method. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Return: DriverState_e - The current running state of the application. +// Throws: None. //-- -bool CMIDriver::SetDriverStateRunningDebugging( void ) +bool +CMIDriver::SetDriverStateRunningDebugging(void) { - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - - if( m_eCurrentDriverState == eDriverState_RunningDebugging ) - return MIstatus::success; - - // Driver cannot be in the following states to set eDriverState_RunningDebugging - switch( m_eCurrentDriverState ) - { - case eDriverState_NotRunning: - case eDriverState_Initialising: - case eDriverState_ShuttingDown: - { - SetErrorDescription( MIRSRC( IDS_DRIVER_ERR_DRIVER_STATE_ERROR ) ); - return MIstatus::failure; - } - case eDriverState_RunningDebugging: - case eDriverState_RunningNotDebugging: - break; - case eDriverState_count: - default: - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CODE_ERR_INVALID_ENUMERATION_VALUE ), "SetDriverStateRunningDebugging()" ) ); - return MIstatus::failure; - } - - // Driver must be in this state to set eDriverState_RunningDebugging - if( m_eCurrentDriverState != eDriverState_RunningNotDebugging ) - { - SetErrorDescription( MIRSRC( IDS_DRIVER_ERR_DRIVER_STATE_ERROR ) ); - return MIstatus::failure; - } - - m_eCurrentDriverState = eDriverState_RunningDebugging; - - return MIstatus::success; + // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM + + if (m_eCurrentDriverState == eDriverState_RunningDebugging) + return MIstatus::success; + + // Driver cannot be in the following states to set eDriverState_RunningDebugging + switch (m_eCurrentDriverState) + { + case eDriverState_NotRunning: + case eDriverState_Initialising: + case eDriverState_ShuttingDown: + { + SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)); + return MIstatus::failure; + } + case eDriverState_RunningDebugging: + case eDriverState_RunningNotDebugging: + break; + case eDriverState_count: + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CODE_ERR_INVALID_ENUMERATION_VALUE), "SetDriverStateRunningDebugging()")); + return MIstatus::failure; + } + + // Driver must be in this state to set eDriverState_RunningDebugging + if (m_eCurrentDriverState != eDriverState_RunningNotDebugging) + { + SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)); + return MIstatus::failure; + } + + m_eCurrentDriverState = eDriverState_RunningDebugging; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Prepare the client IDE so it will start working/communicating with *this MI -// driver. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// Details: Prepare the client IDE so it will start working/communicating with *this MI +// driver. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMIDriver::InitClientIDEToMIDriver( void ) const +bool +CMIDriver::InitClientIDEToMIDriver(void) const { - // Put other IDE init functions here - return InitClientIDEEclipse(); + // Put other IDE init functions here + return InitClientIDEEclipse(); } //++ ------------------------------------------------------------------------------------ // Details: The IDE Eclipse when debugging locally expects "(gdb)\n" character -// sequence otherwise it refuses to communicate and times out. This should be -// sent to Eclipse before anything else. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// sequence otherwise it refuses to communicate and times out. This should be +// sent to Eclipse before anything else. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMIDriver::InitClientIDEEclipse( void ) const +bool +CMIDriver::InitClientIDEEclipse(void) const { - std::cout << "(gdb)" << std::endl; + std::cout << "(gdb)" << std::endl; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Ask *this driver whether it found an executable in the MI Driver's list of -// arguments which to open and debug. If so instigate commands to set up a debug -// session for that executable. -// Type: Method. -// Args: None. -// Return: bool - True = True = Yes executable given as one of the parameters to the MI -// Driver. -// False = not found. -// Throws: None. +// Details: Ask *this driver whether it found an executable in the MI Driver's list of +// arguments which to open and debug. If so instigate commands to set up a debug +// session for that executable. +// Type: Method. +// Args: None. +// Return: bool - True = True = Yes executable given as one of the parameters to the MI +// Driver. +// False = not found. +// Throws: None. //-- -bool CMIDriver::HaveExecutableFileNamePathOnCmdLine( void ) const +bool +CMIDriver::HaveExecutableFileNamePathOnCmdLine(void) const { - return m_bHaveExecutableFileNamePathOnCmdLine; + return m_bHaveExecutableFileNamePathOnCmdLine; } //++ ------------------------------------------------------------------------------------ // Details: Retrieve from *this driver executable file name path to start a debug session -// with (if present see HaveExecutableFileNamePathOnCmdLine()). -// Type: Method. -// Args: None. -// Return: CMIUtilString & - Executeable file name path or empty string. -// Throws: None. +// with (if present see HaveExecutableFileNamePathOnCmdLine()). +// Type: Method. +// Args: None. +// Return: CMIUtilString & - Executeable file name path or empty string. +// Throws: None. //-- -const CMIUtilString & CMIDriver::GetExecutableFileNamePathOnCmdLine( void ) const +const CMIUtilString & +CMIDriver::GetExecutableFileNamePathOnCmdLine(void) const { - return m_strCmdLineArgExecuteableFileNamePath; + return m_strCmdLineArgExecuteableFileNamePath; } //++ ------------------------------------------------------------------------------------ // Details: Execute commands (by injecting them into the stdin line queue container) and -// other code to set up the MI Driver such that is can take the executable -// argument passed on the command and create a debug session for it. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. +// other code to set up the MI Driver such that is can take the executable +// argument passed on the command and create a debug session for it. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. //-- -bool CMIDriver::LocalDebugSessionStartupInjectCommands( void ) +bool +CMIDriver::LocalDebugSessionStartupInjectCommands(void) { - const CMIUtilString strCmd( CMIUtilString::Format( "-file-exec-and-symbols %s", m_strCmdLineArgExecuteableFileNamePath.c_str() ) ); - - return InjectMICommand( strCmd ); + const CMIUtilString strCmd(CMIUtilString::Format("-file-exec-and-symbols %s", m_strCmdLineArgExecuteableFileNamePath.c_str())); + + return InjectMICommand(strCmd); } //++ ------------------------------------------------------------------------------------ // Details: Set the MI Driver into "its debugging an executable passed as an argument" -// mode as against running via a client like Eclipse. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// mode as against running via a client like Eclipse. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMIDriver::SetDriverDebuggingArgExecutable( void ) +void +CMIDriver::SetDriverDebuggingArgExecutable(void) { - m_bDriverDebuggingArgExecutable = true; + m_bDriverDebuggingArgExecutable = true; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the MI Driver state indicating if it is operating in "its debugging -// an executable passed as an argument" mode as against running via a client -// like Eclipse. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: Retrieve the MI Driver state indicating if it is operating in "its debugging +// an executable passed as an argument" mode as against running via a client +// like Eclipse. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -bool CMIDriver::IsDriverDebuggingArgExecutable( void ) const +bool +CMIDriver::IsDriverDebuggingArgExecutable(void) const { - return m_bDriverDebuggingArgExecutable; + return m_bDriverDebuggingArgExecutable; } - diff --git a/tools/lldb-mi/MIDriver.h b/tools/lldb-mi/MIDriver.h index c565e825096e..dafe1bedcf01 100644 --- a/tools/lldb-mi/MIDriver.h +++ b/tools/lldb-mi/MIDriver.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIDriver.h +// File: MIDriver.h // -// Overview: CMIDriver interface. +// Overview: CMIDriver interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -38,145 +38,145 @@ class CMICmnLLDBDebugger; class CMICmnStreamStdout; //++ ============================================================================ -// Details: MI driver implementation class. A singleton class derived from -// LLDB SBBroadcaster class. Register the instance of *this class with -// the CMIDriverMgr. The CMIDriverMgr sets the driver(s) of to start -// work depending on the one selected to work. A driver can if not able -// to handle an instruction or 'command' can pass that command onto -// another driver object registered with the Driver Manager. -// Gotchas: None. -// Authors: Illya Rudkin 29/01/2014. -// Changes: None. +// Details: MI driver implementation class. A singleton class derived from +// LLDB SBBroadcaster class. Register the instance of *this class with +// the CMIDriverMgr. The CMIDriverMgr sets the driver(s) of to start +// work depending on the one selected to work. A driver can if not able +// to handle an instruction or 'command' can pass that command onto +// another driver object registered with the Driver Manager. +// Gotchas: None. +// Authors: Illya Rudkin 29/01/2014. +// Changes: None. //-- -class CMIDriver -: public CMICmnBase -, public CMIDriverMgr::IDriver -, public CMIDriverBase -, public CMICmnStreamStdin::IStreamStdin -, public MI::ISingleton< CMIDriver > +class CMIDriver : public CMICmnBase, + public CMIDriverMgr::IDriver, + public CMIDriverBase, + public CMICmnStreamStdin::IStreamStdin, + public MI::ISingleton { - friend class MI::ISingleton< CMIDriver >; - -// Enumerations: -public: - //++ ---------------------------------------------------------------------- - // Details: The MI Driver has a running state which is used to help determin - // which specific action(s) it should take or not allow. - // The driver when operational and not shutting down alternates - // between eDriverState_RunningNotDebugging and - // eDriverState_RunningDebugging. eDriverState_RunningNotDebugging - // is normally set when a breakpoint is hit or halted. - // eDriverState_RunningDebugging is normally set when "exec-continue" - // or "exec-run" is issued. - //-- - enum DriverState_e - { - eDriverState_NotRunning = 0, // The MI Driver is not operating - eDriverState_Initialising, // The MI Driver is setting itself up - eDriverState_RunningNotDebugging, // The MI Driver is operational acting on any MI commands sent to it - eDriverState_RunningDebugging, // The MI Driver is currently overseeing an inferior program that is running - eDriverState_ShuttingDown, // The MI Driver is tearing down resources and about exit - eDriverState_count // Always last - }; - -// Methods: -public: - // MI system - bool Initialize( void ); - bool Shutdown( void ); - - // MI state - bool GetExitApplicationFlag( void ) const; - DriverState_e GetCurrentDriverState( void ) const; - bool SetDriverStateRunningNotDebugging( void ); - bool SetDriverStateRunningDebugging( void ); - void SetDriverDebuggingArgExecutable( void ); - bool IsDriverDebuggingArgExecutable( void ) const; - - // MI information about itself - const CMIUtilString & GetAppNameShort( void ) const; - const CMIUtilString & GetAppNameLong( void ) const; - const CMIUtilString & GetVersionDescription( void ) const; - - // MI do work - bool WriteMessageToLog( const CMIUtilString & vMessage ); - bool SetEnableFallThru( const bool vbYes ); - bool GetEnableFallThru( void ) const; - bool InjectMICommand( const CMIUtilString & vMICmd ); - bool HaveExecutableFileNamePathOnCmdLine( void ) const; - const CMIUtilString & GetExecutableFileNamePathOnCmdLine( void ) const; - -// Overridden: -public: - // From CMIDriverMgr::IDriver - virtual bool DoInitialize( void ); - virtual bool DoShutdown( void ); - virtual bool DoMainLoop( void ); - virtual void DoResizeWindow( const uint32_t vWindowSizeWsCol ); - virtual lldb::SBError DoParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting ); - virtual CMIUtilString GetError( void ) const; - virtual const CMIUtilString & GetName( void ) const; - virtual lldb::SBDebugger & GetTheDebugger( void ); - virtual bool GetDriverIsGDBMICompatibleDriver( void ) const; - virtual bool SetId( const CMIUtilString & vId ); - virtual const CMIUtilString & GetId( void ) const; - // From CMIDriverBase - virtual void SetExitApplicationFlag( const bool vbForceExit ); - virtual bool DoFallThruToAnotherDriver( const CMIUtilString & vCmd, CMIUtilString & vwErrMsg ); - virtual bool SetDriverToFallThruTo( const CMIDriverBase & vrOtherDriver ); - virtual FILE * GetStdin( void ) const; - virtual FILE * GetStdout( void ) const; - virtual FILE * GetStderr( void ) const; - virtual const CMIUtilString & GetDriverName( void ) const; - virtual const CMIUtilString & GetDriverId( void ) const; - // From CMICmnStreamStdin - virtual bool ReadLine( const CMIUtilString & vStdInBuffer, bool & vrbYesExit ); - -// Typedefs: -private: - typedef std::queue< CMIUtilString > QueueStdinLine_t; - -// Methods: -private: - /* ctor */ CMIDriver( void ); - /* ctor */ CMIDriver( const CMIDriver & ); - void operator=( const CMIDriver & ); - - lldb::SBError ParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting ); - bool ReadStdinLineQueue( void ); - bool DoAppQuit( void ); - bool InterpretCommand( const CMIUtilString & vTextLine ); - bool InterpretCommandThisDriver( const CMIUtilString & vTextLine, bool & vwbCmdYesValid ); - bool InterpretCommandFallThruDriver( const CMIUtilString & vTextLine, bool & vwbCmdYesValid ); - bool ExecuteCommand( const SMICmdData & vCmdData ); - bool StartWorkerThreads( void ); - bool StopWorkerThreads( void ); - bool InitClientIDEToMIDriver( void ) const; - bool InitClientIDEEclipse( void ) const; - bool QueueMICommand( const CMIUtilString & vMICmd ); - bool LocalDebugSessionStartupInjectCommands( void ); - -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMIDriver( void ); - -// Attributes: -private: - static const CMIUtilString ms_constAppNameShort; - static const CMIUtilString ms_constAppNameLong; - static const CMIUtilString ms_constMIVersion; - // - bool m_bFallThruToOtherDriverEnabled; // True = yes fall through, false = do not pass on command - CMIUtilThreadMutex m_threadMutex; - QueueStdinLine_t m_queueStdinLine; // Producer = stdin monitor, consumer = *this driver - bool m_bDriverIsExiting; // True = yes, driver told to quit, false = continue working - void * m_handleMainThread; // *this driver is run by the main thread - CMICmnStreamStdin & m_rStdin; - CMICmnLLDBDebugger & m_rLldbDebugger; - CMICmnStreamStdout & m_rStdOut; - DriverState_e m_eCurrentDriverState; - bool m_bHaveExecutableFileNamePathOnCmdLine; // True = Yes executable given as one of the parameters to the MI Driver, false = not found - CMIUtilString m_strCmdLineArgExecuteableFileNamePath; - bool m_bDriverDebuggingArgExecutable; // True = The MI Driver (MI mode) is debugging executable passed as argument, false = running via a client i.e Eclipse + friend class MI::ISingleton; + + // Enumerations: + public: + //++ ---------------------------------------------------------------------- + // Details: The MI Driver has a running state which is used to help determin + // which specific action(s) it should take or not allow. + // The driver when operational and not shutting down alternates + // between eDriverState_RunningNotDebugging and + // eDriverState_RunningDebugging. eDriverState_RunningNotDebugging + // is normally set when a breakpoint is hit or halted. + // eDriverState_RunningDebugging is normally set when "exec-continue" + // or "exec-run" is issued. + //-- + enum DriverState_e + { + eDriverState_NotRunning = 0, // The MI Driver is not operating + eDriverState_Initialising, // The MI Driver is setting itself up + eDriverState_RunningNotDebugging, // The MI Driver is operational acting on any MI commands sent to it + eDriverState_RunningDebugging, // The MI Driver is currently overseeing an inferior program that is running + eDriverState_ShuttingDown, // The MI Driver is tearing down resources and about exit + eDriverState_count // Always last + }; + + // Methods: + public: + // MI system + bool Initialize(void); + bool Shutdown(void); + + // MI state + bool GetExitApplicationFlag(void) const; + DriverState_e GetCurrentDriverState(void) const; + bool SetDriverStateRunningNotDebugging(void); + bool SetDriverStateRunningDebugging(void); + void SetDriverDebuggingArgExecutable(void); + bool IsDriverDebuggingArgExecutable(void) const; + + // MI information about itself + const CMIUtilString &GetAppNameShort(void) const; + const CMIUtilString &GetAppNameLong(void) const; + const CMIUtilString &GetVersionDescription(void) const; + + // MI do work + bool WriteMessageToLog(const CMIUtilString &vMessage); + bool SetEnableFallThru(const bool vbYes); + bool GetEnableFallThru(void) const; + bool InjectMICommand(const CMIUtilString &vMICmd); + bool HaveExecutableFileNamePathOnCmdLine(void) const; + const CMIUtilString &GetExecutableFileNamePathOnCmdLine(void) const; + + // Overridden: + public: + // From CMIDriverMgr::IDriver + virtual bool DoInitialize(void); + virtual bool DoShutdown(void); + virtual bool DoMainLoop(void); + virtual void DoResizeWindow(const uint32_t vWindowSizeWsCol); + virtual lldb::SBError DoParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting); + virtual CMIUtilString GetError(void) const; + virtual const CMIUtilString &GetName(void) const; + virtual lldb::SBDebugger &GetTheDebugger(void); + virtual bool GetDriverIsGDBMICompatibleDriver(void) const; + virtual bool SetId(const CMIUtilString &vId); + virtual const CMIUtilString &GetId(void) const; + // From CMIDriverBase + virtual void SetExitApplicationFlag(const bool vbForceExit); + virtual bool DoFallThruToAnotherDriver(const CMIUtilString &vCmd, CMIUtilString &vwErrMsg); + virtual bool SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver); + virtual FILE *GetStdin(void) const; + virtual FILE *GetStdout(void) const; + virtual FILE *GetStderr(void) const; + virtual const CMIUtilString &GetDriverName(void) const; + virtual const CMIUtilString &GetDriverId(void) const; + // From CMICmnStreamStdin + virtual bool ReadLine(const CMIUtilString &vStdInBuffer, bool &vrbYesExit); + + // Typedefs: + private: + typedef std::queue QueueStdinLine_t; + + // Methods: + private: + /* ctor */ CMIDriver(void); + /* ctor */ CMIDriver(const CMIDriver &); + void operator=(const CMIDriver &); + + lldb::SBError ParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting); + bool ReadStdinLineQueue(void); + bool DoAppQuit(void); + bool InterpretCommand(const CMIUtilString &vTextLine); + bool InterpretCommandThisDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid); + bool InterpretCommandFallThruDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid); + bool ExecuteCommand(const SMICmdData &vCmdData); + bool StartWorkerThreads(void); + bool StopWorkerThreads(void); + bool InitClientIDEToMIDriver(void) const; + bool InitClientIDEEclipse(void) const; + bool QueueMICommand(const CMIUtilString &vMICmd); + bool LocalDebugSessionStartupInjectCommands(void); + + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMIDriver(void); + + // Attributes: + private: + static const CMIUtilString ms_constAppNameShort; + static const CMIUtilString ms_constAppNameLong; + static const CMIUtilString ms_constMIVersion; + // + bool m_bFallThruToOtherDriverEnabled; // True = yes fall through, false = do not pass on command + CMIUtilThreadMutex m_threadMutex; + QueueStdinLine_t m_queueStdinLine; // Producer = stdin monitor, consumer = *this driver + bool m_bDriverIsExiting; // True = yes, driver told to quit, false = continue working + void *m_handleMainThread; // *this driver is run by the main thread + CMICmnStreamStdin &m_rStdin; + CMICmnLLDBDebugger &m_rLldbDebugger; + CMICmnStreamStdout &m_rStdOut; + DriverState_e m_eCurrentDriverState; + bool m_bHaveExecutableFileNamePathOnCmdLine; // True = Yes executable given as one of the parameters to the MI Driver, false = not found + CMIUtilString m_strCmdLineArgExecuteableFileNamePath; + bool m_bDriverDebuggingArgExecutable; // True = The MI Driver (MI mode) is debugging executable passed as argument, false = running via + // a client i.e Eclipse }; diff --git a/tools/lldb-mi/MIDriverBase.cpp b/tools/lldb-mi/MIDriverBase.cpp index 353f5c32a164..fd9fae821196 100644 --- a/tools/lldb-mi/MIDriverBase.cpp +++ b/tools/lldb-mi/MIDriverBase.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIDriverBase.cpp +// File: MIDriverBase.cpp // -// Overview: CMIDriverBase implementation. +// Overview: CMIDriverBase implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third party headers: @@ -27,169 +27,178 @@ #include "MIDriverBase.h" //++ ------------------------------------------------------------------------------------ -// Details: CMIDriverBase constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIDriverBase constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIDriverBase::CMIDriverBase( void ) -: m_pDriverFallThru( nullptr ) -, m_pDriverParent( nullptr ) -, m_bExitApp( false ) +CMIDriverBase::CMIDriverBase(void) + : m_pDriverFallThru(nullptr) + , m_pDriverParent(nullptr) + , m_bExitApp(false) { } //++ ------------------------------------------------------------------------------------ -// Details: CMIDriverBase destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIDriverBase destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIDriverBase::~CMIDriverBase( void ) +CMIDriverBase::~CMIDriverBase(void) { - m_pDriverFallThru = NULL; + m_pDriverFallThru = NULL; } //++ ------------------------------------------------------------------------------------ -// Details: This function allows *this driver to call on another driver to perform work -// should this driver not be able to handle the client data input. -// Type: Overrideable. -// Check the error message if the function returns a failure. -// Type: Overridden. -// Args: vCmd - (R) Command instruction to interpret. -// vwErrMsg - (W) Error description on command failing. -// Return: MIstatus::success - Command succeeded. -// MIstatus::failure - Command failed. -// Throws: None. +// Details: This function allows *this driver to call on another driver to perform work +// should this driver not be able to handle the client data input. +// Type: Overrideable. +// Check the error message if the function returns a failure. +// Type: Overridden. +// Args: vCmd - (R) Command instruction to interpret. +// vwErrMsg - (W) Error description on command failing. +// Return: MIstatus::success - Command succeeded. +// MIstatus::failure - Command failed. +// Throws: None. //-- -bool CMIDriverBase::DoFallThruToAnotherDriver( const CMIUtilString & vCmd, CMIUtilString & vwErrMsg ) +bool +CMIDriverBase::DoFallThruToAnotherDriver(const CMIUtilString &vCmd, CMIUtilString &vwErrMsg) { - // Do nothing - override and implement. Use m_pDriverFallThru. - return MIstatus::success; + // Do nothing - override and implement. Use m_pDriverFallThru. + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: This function allows *this driver to call on another driver to perform work -// should this driver not be able to handle the client data input. -// Type: Overrideable. -// Args: vrOtherDriver - (R) Reference to another driver object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: This function allows *this driver to call on another driver to perform work +// should this driver not be able to handle the client data input. +// Type: Overrideable. +// Args: vrOtherDriver - (R) Reference to another driver object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriverBase::SetDriverToFallThruTo( const CMIDriverBase & vrOtherDriver ) +bool +CMIDriverBase::SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver) { - MIunused( vrOtherDriver ); + MIunused(vrOtherDriver); - // Do nothing - override and implement. Set m_pDriverFallThru. + // Do nothing - override and implement. Set m_pDriverFallThru. - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: This function allows *this driver to call functionality on the parent driver -// ask for information for example. -// Type: Overrideable. -// Args: vrOtherDriver - (R) Reference to another driver object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: This function allows *this driver to call functionality on the parent driver +// ask for information for example. +// Type: Overrideable. +// Args: vrOtherDriver - (R) Reference to another driver object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriverBase::SetDriverParent( const CMIDriverBase & vrOtherDriver ) +bool +CMIDriverBase::SetDriverParent(const CMIDriverBase &vrOtherDriver) { - MIunused( vrOtherDriver ); + MIunused(vrOtherDriver); - // Do nothing - override and implement. Set m_pDriverParent. + // Do nothing - override and implement. Set m_pDriverParent. - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the parent driver to *this driver if one assigned. If assigned *this -// is the pass through driver that the parent driver passes work to. -// Type: Method. -// Args: None. -// Return: CMIDriverBase * - Pointer to a driver object. -// - NULL = there is not parent to *this driver. -// Throws: None. +// Details: Retrieve the parent driver to *this driver if one assigned. If assigned *this +// is the pass through driver that the parent driver passes work to. +// Type: Method. +// Args: None. +// Return: CMIDriverBase * - Pointer to a driver object. +// - NULL = there is not parent to *this driver. +// Throws: None. //-- -CMIDriverBase * CMIDriverBase::GetDriversParent( void ) const +CMIDriverBase * +CMIDriverBase::GetDriversParent(void) const { - return m_pDriverParent; + return m_pDriverParent; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the pointer to the other fall through driver *this driver is using -// (or not using). -// Type: Method. -// Args: None. -// Return: CMIDriverBase * - Pointer to other driver. -// - NULL if no driver set. -// Throws: None. +// Details: Retrieve the pointer to the other fall through driver *this driver is using +// (or not using). +// Type: Method. +// Args: None. +// Return: CMIDriverBase * - Pointer to other driver. +// - NULL if no driver set. +// Throws: None. //-- -CMIDriverBase * CMIDriverBase::GetDriverToFallThruTo( void ) const +CMIDriverBase * +CMIDriverBase::GetDriverToFallThruTo(void) const { - return m_pDriverFallThru; + return m_pDriverFallThru; } //++ ------------------------------------------------------------------------------------ -// Details: *this driver provides a file stream to other drivers on which *this driver -// write's out to and they read as expected input. *this driver is passing -// through commands to the (child) pass through assigned driver. -// Type: Overrideable. -// Args: None. -// Return: FILE * - Pointer to stream. -// Throws: None. +// Details: *this driver provides a file stream to other drivers on which *this driver +// write's out to and they read as expected input. *this driver is passing +// through commands to the (child) pass through assigned driver. +// Type: Overrideable. +// Args: None. +// Return: FILE * - Pointer to stream. +// Throws: None. //-- -FILE * CMIDriverBase::GetStdin( void ) const +FILE * +CMIDriverBase::GetStdin(void) const { - // Do nothing - override and implement - return nullptr; + // Do nothing - override and implement + return nullptr; } //++ ------------------------------------------------------------------------------------ -// Details: *this driver provides a file stream to other pass through assigned drivers -// so they know what to write to. -// Type: Overrideable. -// Args: None. -// Return: FILE * - Pointer to stream. -// Throws: None. +// Details: *this driver provides a file stream to other pass through assigned drivers +// so they know what to write to. +// Type: Overrideable. +// Args: None. +// Return: FILE * - Pointer to stream. +// Throws: None. //-- -FILE * CMIDriverBase::GetStdout( void ) const +FILE * +CMIDriverBase::GetStdout(void) const { - // Do nothing - override and implement - return nullptr; + // Do nothing - override and implement + return nullptr; } //++ ------------------------------------------------------------------------------------ -// Details: *this driver provides a error file stream to other pass through assigned drivers -// so they know what to write to. -// Type: Overrideable. -// Args: None. -// Return: FILE * - Pointer to stream. -// Throws: None. +// Details: *this driver provides a error file stream to other pass through assigned drivers +// so they know what to write to. +// Type: Overrideable. +// Args: None. +// Return: FILE * - Pointer to stream. +// Throws: None. //-- -FILE * CMIDriverBase::GetStderr( void ) const +FILE * +CMIDriverBase::GetStderr(void) const { - // Do nothing - override and implement - return nullptr; + // Do nothing - override and implement + return nullptr; } //++ ------------------------------------------------------------------------------------ -// Details: Set the MI Driver's exit application flag. The application checks this flag -// after every stdin line is read so the exit may not be instantious. -// If vbForceExit is false the MI Driver queries its state and determines if is -// should exit or continue operating depending on that running state. -// Type: Overrideable. -// Args: vbForceExit - (R) True = Do not query, set state to exit, false = query if can/should exit right now. -// Return: None. -// Throws: None. +// Details: Set the MI Driver's exit application flag. The application checks this flag +// after every stdin line is read so the exit may not be instantious. +// If vbForceExit is false the MI Driver queries its state and determines if is +// should exit or continue operating depending on that running state. +// Type: Overrideable. +// Args: vbForceExit - (R) True = Do not query, set state to exit, false = query if can/should exit right now. +// Return: None. +// Throws: None. //-- -void CMIDriverBase::SetExitApplicationFlag( const bool vbForceExit ) +void +CMIDriverBase::SetExitApplicationFlag(const bool vbForceExit) { - MIunused( vbForceExit ); + MIunused(vbForceExit); - // Do nothing - override and implement -} \ No newline at end of file + // Do nothing - override and implement +} diff --git a/tools/lldb-mi/MIDriverBase.h b/tools/lldb-mi/MIDriverBase.h index ed6b930cfd83..7516efd13b75 100644 --- a/tools/lldb-mi/MIDriverBase.h +++ b/tools/lldb-mi/MIDriverBase.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIDriverBase.h +// File: MIDriverBase.h // -// Overview: CMIDriverBase interface. +// Overview: CMIDriverBase interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -29,50 +29,53 @@ #include "MIUtilString.h" // Declarations: -namespace lldb { class SBBroadcaster; } +namespace lldb +{ +class SBBroadcaster; +} //++ ============================================================================ -// Details: MI driver base implementation class. This class has been created so -// not have to edit the lldb::SBBroadcaster class code. Functionality -// and attributes need to be common to the LLDB Driver class and the -// MI Driver class (derived from lldb::SBBroadcaster) so they can call -// upon each other for functionality fall through and allow the -// CDriverMgr to manage either (any) driver to be operated on. -// Each driver instance (the CMIDriver, LLDB::Driver) has its own -// LLDB::SBDebugger object. -// Gotchas: None. -// Authors: Illya Rudkin 30/01/2014. -// Changes: None. +// Details: MI driver base implementation class. This class has been created so +// not have to edit the lldb::SBBroadcaster class code. Functionality +// and attributes need to be common to the LLDB Driver class and the +// MI Driver class (derived from lldb::SBBroadcaster) so they can call +// upon each other for functionality fall through and allow the +// CDriverMgr to manage either (any) driver to be operated on. +// Each driver instance (the CMIDriver, LLDB::Driver) has its own +// LLDB::SBDebugger object. +// Gotchas: None. +// Authors: Illya Rudkin 30/01/2014. +// Changes: None. //-- class CMIDriverBase { -// Methods: -public: - /* ctor */ CMIDriverBase( void ); - - CMIDriverBase * GetDriverToFallThruTo( void ) const; - CMIDriverBase * GetDriversParent( void ) const; + // Methods: + public: + /* ctor */ CMIDriverBase(void); + + CMIDriverBase *GetDriverToFallThruTo(void) const; + CMIDriverBase *GetDriversParent(void) const; + + // Overrideable: + public: + /* dtor */ virtual ~CMIDriverBase(void); + + virtual bool DoFallThruToAnotherDriver(const CMIUtilString &vCmd, CMIUtilString &vwErrMsg); + virtual bool SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver); + virtual bool SetDriverParent(const CMIDriverBase &vrOtherDriver); + virtual const CMIUtilString &GetDriverName(void) const = 0; + virtual const CMIUtilString &GetDriverId(void) const = 0; + virtual void SetExitApplicationFlag(const bool vbForceExit); + + // MI provide information for the pass through (child) assigned driver + virtual FILE *GetStdin(void) const; + virtual FILE *GetStdout(void) const; + virtual FILE *GetStderr(void) const; -// Overrideable: -public: - /* dtor */ virtual ~CMIDriverBase( void ); - - virtual bool DoFallThruToAnotherDriver( const CMIUtilString & vCmd, CMIUtilString & vwErrMsg ); - virtual bool SetDriverToFallThruTo( const CMIDriverBase & vrOtherDriver ); - virtual bool SetDriverParent( const CMIDriverBase & vrOtherDriver ); - virtual const CMIUtilString & GetDriverName( void ) const = 0; - virtual const CMIUtilString & GetDriverId( void ) const = 0; - virtual void SetExitApplicationFlag( const bool vbForceExit ); - - // MI provide information for the pass through (child) assigned driver - virtual FILE * GetStdin( void ) const; - virtual FILE * GetStdout( void ) const; - virtual FILE * GetStderr( void ) const; - -// Attributes: -protected: - CMIDriverBase * m_pDriverFallThru; // Child driver to use should *this driver not be able to handle client input - CMIDriverBase * m_pDriverParent; // The parent driver who passes work to *this driver to do work - CMIUtilString m_strDriverId; - bool m_bExitApp; // True = Yes, exit application, false = continue execution + // Attributes: + protected: + CMIDriverBase *m_pDriverFallThru; // Child driver to use should *this driver not be able to handle client input + CMIDriverBase *m_pDriverParent; // The parent driver who passes work to *this driver to do work + CMIUtilString m_strDriverId; + bool m_bExitApp; // True = Yes, exit application, false = continue execution }; diff --git a/tools/lldb-mi/MIDriverMain.cpp b/tools/lldb-mi/MIDriverMain.cpp index a72e4ab20f3d..b14fb815b6e6 100644 --- a/tools/lldb-mi/MIDriverMain.cpp +++ b/tools/lldb-mi/MIDriverMain.cpp @@ -8,44 +8,44 @@ //===----------------------------------------------------------------------===// //++ -// File: MIDriverMain.cpp +// File: MIDriverMain.cpp // -// Overview: Defines the entry point for the console application. -// The MI application (project name MI) runs in two modes: -// An LLDB native driver mode where it acts no different from the LLDB driver. -// The other mode is the MI when it finds on the command line -// the --interpreter option. Command line argument --help on its own will give -// help for the LLDB driver. If entered with --interpreter then MI help will -// provided. -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class -// to the command factory. The files of relevance are: -// MICmdCommands.cpp -// MICmdBase.h / .cpp -// MICmdCmd.h / .cpp -// Versions: 1.0.0.1 First version from scratch 28/1/2014 to 28/3/2014. MI not complete. -// 1.0.0.2 First deliverable to client 7/3/2014. MI not complete. -// 1.0.0.3 Code refactor tidy. Release to community for evaluation 17/5/2014. MI not complete. -// 1.0.0.4 Post release to the community for evaluation 17/5/2014. MI not complete. -// 1.0.0.5 Second deliverable to client 16/6/2014. -// 1.0.0.6 Post release of second deliverable to client 16/6/2014. -// Released to the community 24/6/2014. -// 1.0.0.7 Post release to the community. -// Delivered to client 30/6/2014. -// 1.0.0.8 Delivered to client 29/7/2014. -// 1.0.0.9 Post release to client 29/7/2014. -// See MIreadme.txt for list of MI commands implemented. +// Overview: Defines the entry point for the console application. +// The MI application (project name MI) runs in two modes: +// An LLDB native driver mode where it acts no different from the LLDB driver. +// The other mode is the MI when it finds on the command line +// the --interpreter option. Command line argument --help on its own will give +// help for the LLDB driver. If entered with --interpreter then MI help will +// provided. +// To implement new MI commands derive a new command class from the command base +// class. To enable the new command for interpretation add the new command class +// to the command factory. The files of relevance are: +// MICmdCommands.cpp +// MICmdBase.h / .cpp +// MICmdCmd.h / .cpp +// Versions: 1.0.0.1 First version from scratch 28/1/2014 to 28/3/2014. MI not complete. +// 1.0.0.2 First deliverable to client 7/3/2014. MI not complete. +// 1.0.0.3 Code refactor tidy. Release to community for evaluation 17/5/2014. MI not complete. +// 1.0.0.4 Post release to the community for evaluation 17/5/2014. MI not complete. +// 1.0.0.5 Second deliverable to client 16/6/2014. +// 1.0.0.6 Post release of second deliverable to client 16/6/2014. +// Released to the community 24/6/2014. +// 1.0.0.7 Post release to the community. +// Delivered to client 30/6/2014. +// 1.0.0.8 Delivered to client 29/7/2014. +// 1.0.0.9 Post release to client 29/7/2014. +// See MIreadme.txt for list of MI commands implemented. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadme.txt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadme.txt. // -// Copyright: None. +// Copyright: None. //-- -#if defined( _MSC_VER ) - #define _INC_SIGNAL // Stop window's signal.h being included - CODETAG_IOR_SIGNALS -#endif // _MSC_VER +#if defined(_MSC_VER) +#define _INC_SIGNAL // Stop window's signal.h being included - CODETAG_IOR_SIGNALS +#endif // _MSC_VER // Third party headers: #include @@ -53,7 +53,7 @@ // In house headers: #include "MICmnConfig.h" -#include "Platform.h" // Define signals - CODETAG_IOR_SIGNALS +#include "Platform.h" // Define signals - CODETAG_IOR_SIGNALS #include "Driver.h" #include "MIDriverMgr.h" #include "MIDriver.h" @@ -64,330 +64,336 @@ #if MICONFIG_COMPILE_MIDRIVER_VERSION -#if defined( _MSC_VER ) -#pragma warning( once : 4530 ) // Warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc -#endif // _MSC_VER +#if defined(_MSC_VER) +#pragma warning(once : 4530) // Warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc +#endif // _MSC_VER // ToDo: Reevaluate if this function needs to be implemented like the UNIX equivalent // CODETAG_IOR_SIGNALS //++ ------------------------------------------------------------------------------------ -// Details: The SIGWINCH signal is sent to a process when its controlling terminal -// changes its size (a window change). -// Type: Function. -// Args: vSigno - (R) Signal number. -// Return: None. -// Throws: None. +// Details: The SIGWINCH signal is sent to a process when its controlling terminal +// changes its size (a window change). +// Type: Function. +// Args: vSigno - (R) Signal number. +// Return: None. +// Throws: None. //-- -void sigwinch_handler( int vSigno ) +void +sigwinch_handler(int vSigno) { - MIunused( vSigno ); - - struct winsize window_size; - if( ::isatty( STDIN_FILENO ) && ::ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) == 0 ) - { - CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance(); - if( window_size.ws_col > 0 ) - { - rDriverMgr.DriverResizeWindow( (uint32_t) window_size.ws_col ); - } - } - - CMICmnLog::Instance().WriteLog( CMIUtilString::Format( MIRSRC( IDS_PROCESS_SIGNAL_RECEIVED ), "SIGWINCH", vSigno ) ); + MIunused(vSigno); + + struct winsize window_size; + if (::isatty(STDIN_FILENO) && ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) + { + CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); + if (window_size.ws_col > 0) + { + rDriverMgr.DriverResizeWindow((uint32_t)window_size.ws_col); + } + } + + CMICmnLog::Instance().WriteLog(CMIUtilString::Format(MIRSRC(IDS_PROCESS_SIGNAL_RECEIVED), "SIGWINCH", vSigno)); } // CODETAG_IOR_SIGNALS //++ ------------------------------------------------------------------------------------ -// Details: The SIGINT signal is sent to a process by its controlling terminal when a -// user wishes to interrupt the process. This is typically initiated by pressing -// Control-C, but on some systems, the "delete" character or "break" key can be -// used. -// Be aware this function may be called on another thread besides the main thread. -// Type: Function. -// Args: vSigno - (R) Signal number. -// Return: None. -// Throws: None. +// Details: The SIGINT signal is sent to a process by its controlling terminal when a +// user wishes to interrupt the process. This is typically initiated by pressing +// Control-C, but on some systems, the "delete" character or "break" key can be +// used. +// Be aware this function may be called on another thread besides the main thread. +// Type: Function. +// Args: vSigno - (R) Signal number. +// Return: None. +// Throws: None. //-- -void sigint_handler( int vSigno ) +void +sigint_handler(int vSigno) { - static bool g_interrupt_sent = false; - CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance(); - lldb::SBDebugger * pDebugger = rDriverMgr.DriverGetTheDebugger(); - if( pDebugger != nullptr ) - { - if( !g_interrupt_sent ) - { - g_interrupt_sent = true; - pDebugger->DispatchInputInterrupt(); - g_interrupt_sent = false; - } - } - - CMICmnLog::Instance().WriteLog( CMIUtilString::Format( MIRSRC( IDS_PROCESS_SIGNAL_RECEIVED ), "SIGINT", vSigno ) ); - - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - // Signal MI to shutdown or halt a running debug session - CMICmnStreamStdin::Instance().SetCtrlCHit(); + static bool g_interrupt_sent = false; + CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); + lldb::SBDebugger *pDebugger = rDriverMgr.DriverGetTheDebugger(); + if (pDebugger != nullptr) + { + if (!g_interrupt_sent) + { + g_interrupt_sent = true; + pDebugger->DispatchInputInterrupt(); + g_interrupt_sent = false; + } + } + + CMICmnLog::Instance().WriteLog(CMIUtilString::Format(MIRSRC(IDS_PROCESS_SIGNAL_RECEIVED), "SIGINT", vSigno)); + + // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM + // Signal MI to shutdown or halt a running debug session + CMICmnStreamStdin::Instance().SetCtrlCHit(); } // ToDo: Reevaluate if this function needs to be implemented like the UNIX equivalent // CODETAG_IOR_SIGNALS //++ ------------------------------------------------------------------------------------ -// Details: The SIGTSTP signal is sent to a process by its controlling terminal to -// request it to stop temporarily. It is commonly initiated by the user pressing -// Control-Z. Unlike SIGSTOP, the process can register a signal handler for or -// ignore the signal. -// *** The function does not behave ATM like the UNIX equivalent *** -// Type: Function. -// Args: vSigno - (R) Signal number. -// Return: None. -// Throws: None. +// Details: The SIGTSTP signal is sent to a process by its controlling terminal to +// request it to stop temporarily. It is commonly initiated by the user pressing +// Control-Z. Unlike SIGSTOP, the process can register a signal handler for or +// ignore the signal. +// *** The function does not behave ATM like the UNIX equivalent *** +// Type: Function. +// Args: vSigno - (R) Signal number. +// Return: None. +// Throws: None. //-- -void sigtstp_handler( int vSigno ) +void +sigtstp_handler(int vSigno) { - CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance(); - lldb::SBDebugger * pDebugger = rDriverMgr.DriverGetTheDebugger(); - if( pDebugger != nullptr ) - { - pDebugger->SaveInputTerminalState(); - } + CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); + lldb::SBDebugger *pDebugger = rDriverMgr.DriverGetTheDebugger(); + if (pDebugger != nullptr) + { + pDebugger->SaveInputTerminalState(); + } - CMICmnLog::Instance().WriteLog( CMIUtilString::Format( MIRSRC( IDS_PROCESS_SIGNAL_RECEIVED ), "SIGTSTP", vSigno ) ); + CMICmnLog::Instance().WriteLog(CMIUtilString::Format(MIRSRC(IDS_PROCESS_SIGNAL_RECEIVED), "SIGTSTP", vSigno)); - // Signal MI to shutdown - CMICmnStreamStdin::Instance().SetCtrlCHit(); + // Signal MI to shutdown + CMICmnStreamStdin::Instance().SetCtrlCHit(); } // ToDo: Reevaluate if this function needs to be implemented like the UNIX equivalent // CODETAG_IOR_SIGNALS //++ ------------------------------------------------------------------------------------ -// Details: The SIGCONT signal instructs the operating system to continue (restart) a -// process previously paused by the SIGSTOP or SIGTSTP signal. One important use -// of this signal is in job control in the UNIX shell. -// *** The function does not behave ATM like the UNIX equivalent *** -// Type: Function. -// Args: vSigno - (R) Signal number. -// Return: None. -// Throws: None. +// Details: The SIGCONT signal instructs the operating system to continue (restart) a +// process previously paused by the SIGSTOP or SIGTSTP signal. One important use +// of this signal is in job control in the UNIX shell. +// *** The function does not behave ATM like the UNIX equivalent *** +// Type: Function. +// Args: vSigno - (R) Signal number. +// Return: None. +// Throws: None. //-- -void sigcont_handler( int vSigno ) +void +sigcont_handler(int vSigno) { - CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance(); - lldb::SBDebugger * pDebugger = rDriverMgr.DriverGetTheDebugger(); - if( pDebugger != nullptr ) - { - pDebugger->RestoreInputTerminalState(); - } + CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); + lldb::SBDebugger *pDebugger = rDriverMgr.DriverGetTheDebugger(); + if (pDebugger != nullptr) + { + pDebugger->RestoreInputTerminalState(); + } - CMICmnLog::Instance().WriteLog( CMIUtilString::Format( MIRSRC( IDS_PROCESS_SIGNAL_RECEIVED ), "SIGCONT", vSigno ) ); + CMICmnLog::Instance().WriteLog(CMIUtilString::Format(MIRSRC(IDS_PROCESS_SIGNAL_RECEIVED), "SIGCONT", vSigno)); - // Signal MI to shutdown - CMICmnStreamStdin::Instance().SetCtrlCHit(); + // Signal MI to shutdown + CMICmnStreamStdin::Instance().SetCtrlCHit(); } //++ ------------------------------------------------------------------------------------ -// Details: Init the MI driver system. Initialize the whole driver system which includes -// both the original LLDB driver and the MI driver. -// Type: Function. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Init the MI driver system. Initialize the whole driver system which includes +// both the original LLDB driver and the MI driver. +// Type: Function. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool DriverSystemInit( void ) +bool +DriverSystemInit(void) { - bool bOk = MIstatus::success; + bool bOk = MIstatus::success; #if MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER - Driver * pDriver = Driver::CreateSelf(); - if( pDriver == nullptr ) - return MIstatus::failure; + Driver *pDriver = Driver::CreateSelf(); + if (pDriver == nullptr) + return MIstatus::failure; #endif // MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER - CMIDriver & rMIDriver = CMIDriver::Instance(); - CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance(); - bOk = rDriverMgr.Initialize(); + CMIDriver &rMIDriver = CMIDriver::Instance(); + CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); + bOk = rDriverMgr.Initialize(); - // Register MIDriver first as it needs to initialize and be ready - // for the Driver to get information from MIDriver when it initializes - // (LLDB Driver is registered with the Driver Manager in MI's Initialize()) - bOk = bOk && rDriverMgr.RegisterDriver( rMIDriver, "MIDriver" ); // Will be main driver + // Register MIDriver first as it needs to initialize and be ready + // for the Driver to get information from MIDriver when it initializes + // (LLDB Driver is registered with the Driver Manager in MI's Initialize()) + bOk = bOk && rDriverMgr.RegisterDriver(rMIDriver, "MIDriver"); // Will be main driver - return bOk; + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Shutdown the debugger system. Release / terminate resources external to -// specifically the MI driver. -// Type: Function. -// Args: vbAppExitOk - (R) True = No problems, false = App exiting with problems (investigate!). -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Shutdown the debugger system. Release / terminate resources external to +// specifically the MI driver. +// Type: Function. +// Args: vbAppExitOk - (R) True = No problems, false = App exiting with problems (investigate!). +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool DriverSystemShutdown( const bool vbAppExitOk ) +bool +DriverSystemShutdown(const bool vbAppExitOk) { - bool bOk = MIstatus::success; + bool bOk = MIstatus::success; - // *** Order is important here *** - CMIDriverMgr::Instance().Shutdown(); + // *** Order is important here *** + CMIDriverMgr::Instance().Shutdown(); #if MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER - delete g_driver; - g_driver = nullptr; + delete g_driver; + g_driver = nullptr; #endif // MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER - return bOk; + return bOk; } #else void -sigwinch_handler (int signo) +sigwinch_handler(int signo) { struct winsize window_size; - if (isatty (STDIN_FILENO) - && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) + if (isatty(STDIN_FILENO) && ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { if ((window_size.ws_col > 0) && g_driver != NULL) { - g_driver->ResizeWindow (window_size.ws_col); + g_driver->ResizeWindow(window_size.ws_col); } } } void -sigint_handler (int signo) +sigint_handler(int signo) { - static bool g_interrupt_sent = false; + static bool g_interrupt_sent = false; if (g_driver) - { - if (!g_interrupt_sent) - { - g_interrupt_sent = true; - g_driver->GetDebugger().DispatchInputInterrupt(); - g_interrupt_sent = false; - return; - } - } - - exit (signo); + { + if (!g_interrupt_sent) + { + g_interrupt_sent = true; + g_driver->GetDebugger().DispatchInputInterrupt(); + g_interrupt_sent = false; + return; + } + } + + exit(signo); } void -sigtstp_handler (int signo) +sigtstp_handler(int signo) { g_driver->GetDebugger().SaveInputTerminalState(); - signal (signo, SIG_DFL); - kill (getpid(), signo); - signal (signo, sigtstp_handler); + signal(signo, SIG_DFL); + kill(getpid(), signo); + signal(signo, sigtstp_handler); } void -sigcont_handler (int signo) +sigcont_handler(int signo) { g_driver->GetDebugger().RestoreInputTerminalState(); - signal (signo, SIG_DFL); - kill (getpid(), signo); - signal (signo, sigcont_handler); + signal(signo, SIG_DFL); + kill(getpid(), signo); + signal(signo, sigcont_handler); } #endif // #if MICONFIG_COMPILE_MIDRIVER_VERSION //++ ------------------------------------------------------------------------------------ -// Details: MI's application start point of execution. The applicaton runs in two modes. -// An LLDB native driver mode where it acts no different from the LLDB driver. -// The other mode is the MI when it finds on the command line -// the --interpreter option. Command line argument --help on its own will give -// help for the LLDB driver. If entered with --interpreter then application -// help will provided. -// Type: Method. -// Args: argc - (R) An integer that contains the count of arguments that follow in -// argv. The argc parameter is always greater than or equal to 1. -// argv - (R) An array of null-terminated strings representing command-line -// arguments entered by the user of the program. By convention, -// argv[0] is the command with which the program is invoked. -// Return: int - 0 = Normal exit, program success. -// >0 = Program success with status i.e. Control-C signal status -// <0 = Program failed. -// -1 = Program failed reason not specified here, see MI log file. -// -1000 = Program failed did not initailize successfully. -// Throws: None. +// Details: MI's application start point of execution. The applicaton runs in two modes. +// An LLDB native driver mode where it acts no different from the LLDB driver. +// The other mode is the MI when it finds on the command line +// the --interpreter option. Command line argument --help on its own will give +// help for the LLDB driver. If entered with --interpreter then application +// help will provided. +// Type: Method. +// Args: argc - (R) An integer that contains the count of arguments that follow in +// argv. The argc parameter is always greater than or equal to 1. +// argv - (R) An array of null-terminated strings representing command-line +// arguments entered by the user of the program. By convention, +// argv[0] is the command with which the program is invoked. +// Return: int - 0 = Normal exit, program success. +// >0 = Program success with status i.e. Control-C signal status +// <0 = Program failed. +// -1 = Program failed reason not specified here, see MI log file. +// -1000 = Program failed did not initailize successfully. +// Throws: None. //-- #if MICONFIG_COMPILE_MIDRIVER_VERSION -int main( int argc, char const *argv[] ) +int +main(int argc, char const *argv[]) { #if MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG #ifdef _WIN32 - CMIUtilDebug::ShowDlgWaitForDbgAttach(); + CMIUtilDebug::ShowDlgWaitForDbgAttach(); #else - CMIUtilDebug::WaitForDbgAttachInfinteLoop(); + CMIUtilDebug::WaitForDbgAttachInfinteLoop(); #endif // _WIN32 #endif // MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG - // *** Order is important here *** - bool bOk = DriverSystemInit(); - if( !bOk ) - { - DriverSystemShutdown( bOk ); - return -1000; - } - - // CODETAG_IOR_SIGNALS - signal( SIGPIPE, SIG_IGN ); - signal( SIGWINCH, sigwinch_handler ); - signal( SIGINT, sigint_handler ); - signal( SIGTSTP, sigtstp_handler ); - signal( SIGCONT, sigcont_handler ); - - bool bExiting = false; - CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance(); - bOk = bOk && rDriverMgr.ParseArgs( argc, argv, bExiting ); - if( bOk && !bExiting ) - bOk = rDriverMgr.DriverParseArgs( argc, argv, stdout, bExiting ); - if( bOk && !bExiting ) - bOk = rDriverMgr.DriverMainLoop(); - - // Logger and other resources shutdown now - DriverSystemShutdown( bOk ); - - const int appResult = bOk ? 0 : -1; - - return appResult; + // *** Order is important here *** + bool bOk = DriverSystemInit(); + if (!bOk) + { + DriverSystemShutdown(bOk); + return -1000; + } + + // CODETAG_IOR_SIGNALS + signal(SIGPIPE, SIG_IGN); + signal(SIGWINCH, sigwinch_handler); + signal(SIGINT, sigint_handler); + signal(SIGTSTP, sigtstp_handler); + signal(SIGCONT, sigcont_handler); + + bool bExiting = false; + CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); + bOk = bOk && rDriverMgr.ParseArgs(argc, argv, bExiting); + if (bOk && !bExiting) + bOk = rDriverMgr.DriverParseArgs(argc, argv, stdout, bExiting); + if (bOk && !bExiting) + bOk = rDriverMgr.DriverMainLoop(); + + // Logger and other resources shutdown now + DriverSystemShutdown(bOk); + + const int appResult = bOk ? 0 : -1; + + return appResult; } -#else // Operate the lldb Driver only version of the code -int main(int argc, char const *argv[], char *envp[]) +#else // Operate the lldb Driver only version of the code +int +main(int argc, char const *argv[], char *envp[]) { - MIunused( envp ); - using namespace lldb; - SBDebugger::Initialize(); - - SBHostOS::ThreadCreated (""); - - signal (SIGPIPE, SIG_IGN); - signal (SIGWINCH, sigwinch_handler); - signal (SIGINT, sigint_handler); - signal (SIGTSTP, sigtstp_handler); - signal (SIGCONT, sigcont_handler); - - // Create a scope for driver so that the driver object will destroy itself - // before SBDebugger::Terminate() is called. - { - Driver driver; - - bool exiting = false; - SBError error (driver.ParseArgs (argc, argv, stdout, exiting)); - if (error.Fail()) - { - const char *error_cstr = error.GetCString (); - if (error_cstr) - ::fprintf (stderr, "error: %s\n", error_cstr); - } - else if (!exiting) - { - driver.MainLoop(); - } - } - - SBDebugger::Terminate(); - return 0; + MIunused(envp); + using namespace lldb; + SBDebugger::Initialize(); + + SBHostOS::ThreadCreated(""); + + signal(SIGPIPE, SIG_IGN); + signal(SIGWINCH, sigwinch_handler); + signal(SIGINT, sigint_handler); + signal(SIGTSTP, sigtstp_handler); + signal(SIGCONT, sigcont_handler); + + // Create a scope for driver so that the driver object will destroy itself + // before SBDebugger::Terminate() is called. + { + Driver driver; + + bool exiting = false; + SBError error(driver.ParseArgs(argc, argv, stdout, exiting)); + if (error.Fail()) + { + const char *error_cstr = error.GetCString(); + if (error_cstr) + ::fprintf(stderr, "error: %s\n", error_cstr); + } + else if (!exiting) + { + driver.MainLoop(); + } + } + + SBDebugger::Terminate(); + return 0; } #endif // MICONFIG_COMPILE_MIDRIVER_VERSION - diff --git a/tools/lldb-mi/MIDriverMgr.cpp b/tools/lldb-mi/MIDriverMgr.cpp index b5cb7d4b5151..79b44ca947ad 100644 --- a/tools/lldb-mi/MIDriverMgr.cpp +++ b/tools/lldb-mi/MIDriverMgr.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIDriverMgr.cpp +// File: MIDriverMgr.cpp // -// Overview: CMIDriverMgr implementation. +// Overview: CMIDriverMgr implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third Party Headers: @@ -33,730 +33,752 @@ #include "MIUtilSingletonHelper.h" //++ ------------------------------------------------------------------------------------ -// Details: CMIDriverMgr constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIDriverMgr constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIDriverMgr::CMIDriverMgr( void ) -: m_pDriverCurrent( nullptr ) -, m_bInMi2Mode( false ) +CMIDriverMgr::CMIDriverMgr(void) + : m_pDriverCurrent(nullptr) + , m_bInMi2Mode(false) { } //++ ------------------------------------------------------------------------------------ -// Details: CMIDriverMgr destructor. -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIDriverMgr destructor. +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIDriverMgr::~CMIDriverMgr( void ) +CMIDriverMgr::~CMIDriverMgr(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize *this manager. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialize *this manager. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriverMgr::Initialize( void ) +bool +CMIDriverMgr::Initialize(void) { - m_clientUsageRefCnt++; - - ClrErrorDescription(); - - if( m_bInitialized ) - return MIstatus::success; - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Note initialisation order is important here as some resources depend on previous - MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); - MI::ModuleInit< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg ); - - if( bOk ) - { - MIUtilTermios::StdinTermiosSet(); - } - - m_bInitialized = bOk; - - if( !bOk ) - { - CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_DRIVERMGR ), errMsg.c_str() ) ); - SetErrorDescription( strInitError ); - return MIstatus::failure; - } - - return bOk; + m_clientUsageRefCnt++; + + ClrErrorDescription(); + + if (m_bInitialized) + return MIstatus::success; + + bool bOk = MIstatus::success; + CMIUtilString errMsg; + + // Note initialisation order is important here as some resources depend on previous + MI::ModuleInit(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + MI::ModuleInit(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + + if (bOk) + { + MIUtilTermios::StdinTermiosSet(); + } + + m_bInitialized = bOk; + + if (!bOk) + { + CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_DRIVERMGR), errMsg.c_str())); + SetErrorDescription(strInitError); + return MIstatus::failure; + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Unbind detach or release resources used by this server in general common -// functionality shared between versions of any server interfaces implemented. -// Type: Method. -// Args: vbAppExitOk - (R) True = No problems, false = App exiting with problems (investigate!). -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Unbind detach or release resources used by this server in general common +// functionality shared between versions of any server interfaces implemented. +// Type: Method. +// Args: vbAppExitOk - (R) True = No problems, false = App exiting with problems (investigate!). +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriverMgr::Shutdown( void ) +bool +CMIDriverMgr::Shutdown(void) { - // Do not want a ref counter because this function needs to be called how ever this - // application stops running - //if( --m_clientUsageRefCnt > 0 ) - // return MIstatus::success; - - bool vbAppExitOk = true; - - ClrErrorDescription(); - - if( !m_bInitialized ) - return MIstatus::success; - - if( vbAppExitOk ) - { - // The MI Driver's log updating may have been switched off switch back on to say all is ok. - CMICmnLog::Instance().SetEnabled( true ); + // Do not want a ref counter because this function needs to be called how ever this + // application stops running + // if( --m_clientUsageRefCnt > 0 ) + // return MIstatus::success; + + bool vbAppExitOk = true; + + ClrErrorDescription(); + + if (!m_bInitialized) + return MIstatus::success; + + if (vbAppExitOk) + { + // The MI Driver's log updating may have been switched off switch back on to say all is ok. + CMICmnLog::Instance().SetEnabled(true); #if _DEBUG - CMICmnStreamStdout::Instance().Write( MIRSRC( IDE_MI_APP_EXIT_OK ) ); // Both stdout and Log + CMICmnStreamStdout::Instance().Write(MIRSRC(IDE_MI_APP_EXIT_OK)); // Both stdout and Log #else - CMICmnLog::WriteLog( MIRSRC( IDE_MI_APP_EXIT_OK ) ); // Just to the Log + CMICmnLog::WriteLog(MIRSRC(IDE_MI_APP_EXIT_OK)); // Just to the Log #endif // _DEBUG - } - else - { - CMICmnLog & rAppLog = CMICmnLog::Instance(); - if( rAppLog.GetEnabled() ) - { - const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDE_MI_APP_EXIT_WITH_PROBLEM ), CMICmnLogMediumFile::Instance().GetFileName().c_str() ) ); - CMICmnStreamStdout::Instance().Write( msg ); - } - else - { - // The MI Driver's log updating may have been switched off switch back on to say there has been problem. - rAppLog.SetEnabled( true ); - const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDE_MI_APP_EXIT_WITH_PROBLEM_NO_LOG ), CMICmnLogMediumFile::Instance().GetFileName().c_str() ) ); - CMICmnStreamStdout::Instance().Write( msg ); - } - } - - m_bInitialized = false; - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Tidy up - UnregisterDriverAll(); - MIUtilTermios::StdinTermiosReset(); - - // Note shutdown order is important here - MI::ModuleShutdown< CMICmnResources >( IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg ); - MI::ModuleShutdown< CMICmnLog > ( IDS_MI_SHTDWN_ERR_LOG , bOk, errMsg ); - - if( !bOk ) - { - SetErrorDescriptionn( MIRSRC( IDS_MI_SHTDWN_ERR_DRIVERMGR ), errMsg.c_str() ); - } - - return bOk; + } + else + { + CMICmnLog &rAppLog = CMICmnLog::Instance(); + if (rAppLog.GetEnabled()) + { + const CMIUtilString msg( + CMIUtilString::Format(MIRSRC(IDE_MI_APP_EXIT_WITH_PROBLEM), CMICmnLogMediumFile::Instance().GetFileName().c_str())); + CMICmnStreamStdout::Instance().Write(msg); + } + else + { + // The MI Driver's log updating may have been switched off switch back on to say there has been problem. + rAppLog.SetEnabled(true); + const CMIUtilString msg( + CMIUtilString::Format(MIRSRC(IDE_MI_APP_EXIT_WITH_PROBLEM_NO_LOG), CMICmnLogMediumFile::Instance().GetFileName().c_str())); + CMICmnStreamStdout::Instance().Write(msg); + } + } + + m_bInitialized = false; + + bool bOk = MIstatus::success; + CMIUtilString errMsg; + + // Tidy up + UnregisterDriverAll(); + MIUtilTermios::StdinTermiosReset(); + + // Note shutdown order is important here + MI::ModuleShutdown(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg); + MI::ModuleShutdown(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg); + + if (!bOk) + { + SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_DRIVERMGR), errMsg.c_str()); + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Unregister all the Driver registered with *this manager. The manager also -// deletes -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Unregister all the Driver registered with *this manager. The manager also +// deletes +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriverMgr::UnregisterDriverAll( void ) +bool +CMIDriverMgr::UnregisterDriverAll(void) { - MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); - while( it != m_mapDriverIdToDriver.end() ) - { - IDriver * pDriver = (*it).second; - pDriver->DoShutdown(); - - // Next - ++it; - } - - m_mapDriverIdToDriver.clear(); - m_pDriverCurrent = NULL; - - return MIstatus::success; + MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); + while (it != m_mapDriverIdToDriver.end()) + { + IDriver *pDriver = (*it).second; + pDriver->DoShutdown(); + + // Next + ++it; + } + + m_mapDriverIdToDriver.clear(); + m_pDriverCurrent = NULL; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Register a driver with *this Driver Manager. Call SetUseThisDriverToDoWork() -// inform the manager which driver is the one to the work. The manager calls -// the driver's init function which must be successful in order to complete the -// registration. -// Type: Method. -// Args: vrDriver - (R) The driver to register. -// vrDriverID - (R) The driver's ID to lookup by. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Register a driver with *this Driver Manager. Call SetUseThisDriverToDoWork() +// inform the manager which driver is the one to the work. The manager calls +// the driver's init function which must be successful in order to complete the +// registration. +// Type: Method. +// Args: vrDriver - (R) The driver to register. +// vrDriverID - (R) The driver's ID to lookup by. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriverMgr::RegisterDriver( const IDriver & vrDriver, const CMIUtilString & vrDriverID ) +bool +CMIDriverMgr::RegisterDriver(const IDriver &vrDriver, const CMIUtilString &vrDriverID) { - if( HaveDriverAlready( vrDriver ) ) - return MIstatus::success; - - IDriver * pDriver = const_cast< IDriver * >( &vrDriver ); - if( !pDriver->SetId( vrDriverID ) ) - return MIstatus::failure; - if( !pDriver->DoInitialize() ) - { - SetErrorDescriptionn( MIRSRC( IDS_DRIVERMGR_DRIVER_ERR_INIT ), pDriver->GetName().c_str(), vrDriverID.c_str(), pDriver->GetError().c_str() ); - return MIstatus::failure; - } - - MapPairDriverIdToDriver_t pr( vrDriverID, pDriver ); - m_mapDriverIdToDriver.insert( pr ); - - return MIstatus::success; + if (HaveDriverAlready(vrDriver)) + return MIstatus::success; + + IDriver *pDriver = const_cast(&vrDriver); + if (!pDriver->SetId(vrDriverID)) + return MIstatus::failure; + if (!pDriver->DoInitialize()) + { + SetErrorDescriptionn(MIRSRC(IDS_DRIVERMGR_DRIVER_ERR_INIT), pDriver->GetName().c_str(), vrDriverID.c_str(), + pDriver->GetError().c_str()); + return MIstatus::failure; + } + + MapPairDriverIdToDriver_t pr(vrDriverID, pDriver); + m_mapDriverIdToDriver.insert(pr); + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Query the Driver Manager to see if *this manager has the driver already -// registered. -// Type: Method. -// Args: vrDriver - (R) The driver to query. -// Return: True - registered. -// False - not registered. -// Throws: None. +// Details: Query the Driver Manager to see if *this manager has the driver already +// registered. +// Type: Method. +// Args: vrDriver - (R) The driver to query. +// Return: True - registered. +// False - not registered. +// Throws: None. //-- -bool CMIDriverMgr::HaveDriverAlready( const IDriver & vrDriver ) const +bool +CMIDriverMgr::HaveDriverAlready(const IDriver &vrDriver) const { - MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); - while( it != m_mapDriverIdToDriver.end() ) - { - const IDriver * pDrvr = (*it).second; - if( pDrvr == &vrDriver ) - return true; - - // Next - ++it; - } - - return false; + MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); + while (it != m_mapDriverIdToDriver.end()) + { + const IDriver *pDrvr = (*it).second; + if (pDrvr == &vrDriver) + return true; + + // Next + ++it; + } + + return false; } //++ ------------------------------------------------------------------------------------ -// Details: Unregister a driver from the Driver Manager. Call the SetUseThisDriverToDoWork() -// function to define another driver to do work if the one being unregistered did -// the work previously. -// Type: Method. -// Args: vrDriver - (R) The driver to unregister. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Unregister a driver from the Driver Manager. Call the SetUseThisDriverToDoWork() +// function to define another driver to do work if the one being unregistered did +// the work previously. +// Type: Method. +// Args: vrDriver - (R) The driver to unregister. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriverMgr::UnregisterDriver( const IDriver & vrDriver ) +bool +CMIDriverMgr::UnregisterDriver(const IDriver &vrDriver) { - const IDriver * pDrvr = nullptr; - MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); - while( it != m_mapDriverIdToDriver.end() ) - { - pDrvr = (*it).second; - if( pDrvr == &vrDriver ) - break; - - // Next - ++it; - } - m_mapDriverIdToDriver.erase( it ); - - if( m_pDriverCurrent == pDrvr ) - m_pDriverCurrent = nullptr; - - return MIstatus::success; + const IDriver *pDrvr = nullptr; + MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); + while (it != m_mapDriverIdToDriver.end()) + { + pDrvr = (*it).second; + if (pDrvr == &vrDriver) + break; + + // Next + ++it; + } + m_mapDriverIdToDriver.erase(it); + + if (m_pDriverCurrent == pDrvr) + m_pDriverCurrent = nullptr; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Specify the driver to do work. The Driver Manager drives this driver. Any -// previous driver doing work is not called anymore (so be sure the previous -// driver is in a tidy state before stopping it working). -// Type: Method. -// Args: vrADriver - (R) A lldb::SBBroadcaster/IDriver derived object. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Specify the driver to do work. The Driver Manager drives this driver. Any +// previous driver doing work is not called anymore (so be sure the previous +// driver is in a tidy state before stopping it working). +// Type: Method. +// Args: vrADriver - (R) A lldb::SBBroadcaster/IDriver derived object. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriverMgr::SetUseThisDriverToDoWork( const IDriver & vrADriver ) +bool +CMIDriverMgr::SetUseThisDriverToDoWork(const IDriver &vrADriver) { - m_pDriverCurrent = const_cast< IDriver * >( &vrADriver ); + m_pDriverCurrent = const_cast(&vrADriver); - const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_SAY_DRIVER_USING ), m_pDriverCurrent->GetName().c_str() ) ); - m_pLog->Write( msg, CMICmnLog::eLogVerbosity_Log ); + const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_SAY_DRIVER_USING), m_pDriverCurrent->GetName().c_str())); + m_pLog->Write(msg, CMICmnLog::eLogVerbosity_Log); - m_bInMi2Mode = m_pDriverCurrent->GetDriverIsGDBMICompatibleDriver(); + m_bInMi2Mode = m_pDriverCurrent->GetDriverIsGDBMICompatibleDriver(); - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Ask *this manager which driver is currently doing the work. -// Type: Method. -// Args: None. -// Return: IDriver * - Pointer to a driver, NULL if there is no current working driver. -// Throws: None. +// Details: Ask *this manager which driver is currently doing the work. +// Type: Method. +// Args: None. +// Return: IDriver * - Pointer to a driver, NULL if there is no current working driver. +// Throws: None. //-- -CMIDriverMgr::IDriver * CMIDriverMgr::GetUseThisDriverToDoWork( void ) const +CMIDriverMgr::IDriver * +CMIDriverMgr::GetUseThisDriverToDoWork(void) const { - return m_pDriverCurrent; + return m_pDriverCurrent; } //++ ------------------------------------------------------------------------------------ -// Details: Call this function puts *this driver to work. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Call this function puts *this driver to work. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriverMgr::DriverMainLoop( void ) +bool +CMIDriverMgr::DriverMainLoop(void) { - if( m_pDriverCurrent != nullptr ) - { - if( !m_pDriverCurrent->DoMainLoop() ) - { - const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_MAINLOOP ), m_pDriverCurrent->GetError().c_str() ) ); - CMICmnStreamStdout::Instance().Write( errMsg, true ); - return MIstatus::failure; - } - } - else - { - const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) ); - CMICmnStreamStdout::Instance().Write( errMsg, true ); - return MIstatus::failure; - } - - return MIstatus::success; + if (m_pDriverCurrent != nullptr) + { + if (!m_pDriverCurrent->DoMainLoop()) + { + const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_MAINLOOP), m_pDriverCurrent->GetError().c_str())); + CMICmnStreamStdout::Instance().Write(errMsg, true); + return MIstatus::failure; + } + } + else + { + const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET))); + CMICmnStreamStdout::Instance().Write(errMsg, true); + return MIstatus::failure; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Call *this driver to resize the console window. -// Type: Method. -// Args: vWindowSizeWsCol - (R) New window column size. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Call *this driver to resize the console window. +// Type: Method. +// Args: vWindowSizeWsCol - (R) New window column size. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -void CMIDriverMgr::DriverResizeWindow( const uint32_t vWindowSizeWsCol ) +void +CMIDriverMgr::DriverResizeWindow(const uint32_t vWindowSizeWsCol) { - if( m_pDriverCurrent != nullptr ) - return m_pDriverCurrent->DoResizeWindow( vWindowSizeWsCol ); - else - { - const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) ); - CMICmnStreamStdout::Instance().Write( errMsg, true ); - } + if (m_pDriverCurrent != nullptr) + return m_pDriverCurrent->DoResizeWindow(vWindowSizeWsCol); + else + { + const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET))); + CMICmnStreamStdout::Instance().Write(errMsg, true); + } } //++ ------------------------------------------------------------------------------------ -// Details: Get the current driver to validate executable command line arguments. -// Type: Method. -// Args: argc - (R) An integer that contains the count of arguments that follow in -// argv. The argc parameter is always greater than or equal to 1. -// argv - (R) An array of null-terminated strings representing command-line -// arguments entered by the user of the program. By convention, -// argv[0] is the command with which the program is invoked. -// vpStdOut - (R) Point to a standard output stream. -// vwbExiting - (W) True = *this want to exit, false = continue to work. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Get the current driver to validate executable command line arguments. +// Type: Method. +// Args: argc - (R) An integer that contains the count of arguments that follow in +// argv. The argc parameter is always greater than or equal to 1. +// argv - (R) An array of null-terminated strings representing command-line +// arguments entered by the user of the program. By convention, +// argv[0] is the command with which the program is invoked. +// vpStdOut - (R) Point to a standard output stream. +// vwbExiting - (W) True = *this want to exit, false = continue to work. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIDriverMgr::DriverParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting ) +bool +CMIDriverMgr::DriverParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting) { - if( m_pDriverCurrent == nullptr ) - { - const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) ); - CMICmnStreamStdout::Instance().Write( errMsg, true ); - return MIstatus::failure; - } - - const lldb::SBError error( m_pDriverCurrent->DoParseArgs( argc, argv, vpStdOut, vwbExiting ) ); - bool bOk = !error.Fail(); - if( !bOk ) - { - CMIUtilString errMsg; - const MIchar * pErrorCstr = error.GetCString(); - if( pErrorCstr != nullptr ) - errMsg = CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_PARSE_ARGS ), m_pDriverCurrent->GetName().c_str(), pErrorCstr ); - else - errMsg = CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN ), m_pDriverCurrent->GetName().c_str() ); - - bOk = CMICmnStreamStdout::Instance().Write( errMsg, true ); - } - - return bOk; + if (m_pDriverCurrent == nullptr) + { + const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET))); + CMICmnStreamStdout::Instance().Write(errMsg, true); + return MIstatus::failure; + } + + const lldb::SBError error(m_pDriverCurrent->DoParseArgs(argc, argv, vpStdOut, vwbExiting)); + bool bOk = !error.Fail(); + if (!bOk) + { + CMIUtilString errMsg; + const MIchar *pErrorCstr = error.GetCString(); + if (pErrorCstr != nullptr) + errMsg = CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_PARSE_ARGS), m_pDriverCurrent->GetName().c_str(), pErrorCstr); + else + errMsg = CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN), m_pDriverCurrent->GetName().c_str()); + + bOk = CMICmnStreamStdout::Instance().Write(errMsg, true); + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the current driver's last error condition. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Text description. -// Throws: None. +// Details: Retrieve the current driver's last error condition. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Text description. +// Throws: None. //-- -CMIUtilString CMIDriverMgr::DriverGetError( void ) const +CMIUtilString +CMIDriverMgr::DriverGetError(void) const { - if( m_pDriverCurrent != nullptr ) - return m_pDriverCurrent->GetError(); - else - { - const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) ); - CMICmnStreamStdout::Instance().Write( errMsg, true ); - } - - return CMIUtilString(); + if (m_pDriverCurrent != nullptr) + return m_pDriverCurrent->GetError(); + else + { + const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET))); + CMICmnStreamStdout::Instance().Write(errMsg, true); + } + + return CMIUtilString(); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the current driver's name. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Driver name. -// Empty string = no current working driver specified. -// Throws: None. +// Details: Retrieve the current driver's name. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Driver name. +// Empty string = no current working driver specified. +// Throws: None. //-- -CMIUtilString CMIDriverMgr::DriverGetName( void ) const +CMIUtilString +CMIDriverMgr::DriverGetName(void) const { - if( m_pDriverCurrent != nullptr ) - return m_pDriverCurrent->GetName(); - else - { - const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) ); - CMICmnStreamStdout::Instance().Write( errMsg, true ); - } - - return CMIUtilString(); + if (m_pDriverCurrent != nullptr) + return m_pDriverCurrent->GetName(); + else + { + const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET))); + CMICmnStreamStdout::Instance().Write(errMsg, true); + } + + return CMIUtilString(); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the current driver's debugger object. -// Type: Method. -// Args: None. -// Return: lldb::SBDebugger * - Ptr to driver's debugger object. -// - NULL = no current working driver specified. -// Throws: None. +// Details: Retrieve the current driver's debugger object. +// Type: Method. +// Args: None. +// Return: lldb::SBDebugger * - Ptr to driver's debugger object. +// - NULL = no current working driver specified. +// Throws: None. //-- -lldb::SBDebugger * CMIDriverMgr::DriverGetTheDebugger( void ) +lldb::SBDebugger * +CMIDriverMgr::DriverGetTheDebugger(void) { - lldb::SBDebugger * pDebugger = nullptr; - if( m_pDriverCurrent != nullptr ) - pDebugger = &m_pDriverCurrent->GetTheDebugger(); - else - { - const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) ); - CMICmnStreamStdout::Instance().Write( errMsg, true ); - } - - return pDebugger; + lldb::SBDebugger *pDebugger = nullptr; + if (m_pDriverCurrent != nullptr) + pDebugger = &m_pDriverCurrent->GetTheDebugger(); + else + { + const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET))); + CMICmnStreamStdout::Instance().Write(errMsg, true); + } + + return pDebugger; } //++ ------------------------------------------------------------------------------------ -// Details: Check the arguments given on the command line. The main purpose of this -// function is to check for the presence of the --interpreter option. Having -// this option present tells *this manager to set the CMIDriver to do work. If -// not use the LLDB driver. The following are options that are only handled by -// the CMIDriverMgr are: -// --help or -h -// --interpreter -// --version -// --versionLong -// --noLog -// --executable -// The above arguments are not handled by any driver object except for --executable. -// The options --interpreter and --executable in code act very similar. The -// --executable is necessary to differentiate whither the MI Driver is being using -// by a client i.e. Eclipse or from the command line. Eclipse issues the option -// --interpreter and also passes additional arguments which can be interpreted as an -// executable if called from the command line. Using --executable tells the MI -// Driver is being called the command line and that the executable argument is indeed -// a specified executable an so actions commands to set up the executable for a -// debug session. Using --interpreter on the commnd line does not action additional -// commands to initialise a debug session and so be able to launch the process. -// Type: Method. -// Args: argc - (R) An integer that contains the count of arguments that follow in -// argv. The argc parameter is always greater than or equal to 1. -// argv - (R) An array of null-terminated strings representing command-line -// arguments entered by the user of the program. By convention, -// argv[0] is the command with which the program is invoked. -// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s), -// version information only. -// False = Continue to work, start debugger i.e. Command -// interpreter. -// Return: lldb::SBError - LLDB current error status. -// Throws: None. +// Details: Check the arguments given on the command line. The main purpose of this +// function is to check for the presence of the --interpreter option. Having +// this option present tells *this manager to set the CMIDriver to do work. If +// not use the LLDB driver. The following are options that are only handled by +// the CMIDriverMgr are: +// --help or -h +// --interpreter +// --version +// --versionLong +// --noLog +// --executable +// The above arguments are not handled by any driver object except for --executable. +// The options --interpreter and --executable in code act very similar. The +// --executable is necessary to differentiate whither the MI Driver is being using +// by a client i.e. Eclipse or from the command line. Eclipse issues the option +// --interpreter and also passes additional arguments which can be interpreted as an +// executable if called from the command line. Using --executable tells the MI +// Driver is being called the command line and that the executable argument is indeed +// a specified executable an so actions commands to set up the executable for a +// debug session. Using --interpreter on the commnd line does not action additional +// commands to initialise a debug session and so be able to launch the process. +// Type: Method. +// Args: argc - (R) An integer that contains the count of arguments that follow in +// argv. The argc parameter is always greater than or equal to 1. +// argv - (R) An array of null-terminated strings representing command-line +// arguments entered by the user of the program. By convention, +// argv[0] is the command with which the program is invoked. +// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s), +// version information only. +// False = Continue to work, start debugger i.e. Command +// interpreter. +// Return: lldb::SBError - LLDB current error status. +// Throws: None. //-- -bool CMIDriverMgr::ParseArgs( const int argc, const char * argv[], bool & vwbExiting ) +bool +CMIDriverMgr::ParseArgs(const int argc, const char *argv[], bool &vwbExiting) { - bool bOk = MIstatus::success; - - vwbExiting = false; - - // Print MI application path to the Log file - const CMIUtilString appPath( CMIUtilString::Format( MIRSRC( IDS_MI_APP_FILEPATHNAME ), argv[ 0 ] ) ); - bOk = m_pLog->Write( appPath, CMICmnLog::eLogVerbosity_Log ); - - // Print application arguments to the Log file - const bool bHaveArgs( argc >= 2 ); - CMIUtilString strArgs( MIRSRC( IDS_MI_APP_ARGS ) ); - if( !bHaveArgs ) - { - strArgs += MIRSRC( IDS_WORD_NONE ); - bOk = bOk && m_pLog->Write( strArgs, CMICmnLog::eLogVerbosity_Log ); - } - else - { - for( MIint i = 1; i < argc; i++ ) - { - strArgs += CMIUtilString::Format( "%d:'%s' ", i, argv[ i ] ); - } - bOk = bOk && m_pLog->Write( strArgs, CMICmnLog::eLogVerbosity_Log ); - } - - // Look for the command line options - bool bHaveArgInterpret = false; - bool bHaveArgVersion = false; - bool bHaveArgVersionLong = false; - bool bHaveArgNoLog = false; - bool bHaveArgHelp = false; - - // Hardcode the use of the MI driver + bool bOk = MIstatus::success; + + vwbExiting = false; + + // Print MI application path to the Log file + const CMIUtilString appPath(CMIUtilString::Format(MIRSRC(IDS_MI_APP_FILEPATHNAME), argv[0])); + bOk = m_pLog->Write(appPath, CMICmnLog::eLogVerbosity_Log); + + // Print application arguments to the Log file + const bool bHaveArgs(argc >= 2); + CMIUtilString strArgs(MIRSRC(IDS_MI_APP_ARGS)); + if (!bHaveArgs) + { + strArgs += MIRSRC(IDS_WORD_NONE); + bOk = bOk && m_pLog->Write(strArgs, CMICmnLog::eLogVerbosity_Log); + } + else + { + for (MIint i = 1; i < argc; i++) + { + strArgs += CMIUtilString::Format("%d:'%s' ", i, argv[i]); + } + bOk = bOk && m_pLog->Write(strArgs, CMICmnLog::eLogVerbosity_Log); + } + + // Look for the command line options + bool bHaveArgInterpret = false; + bool bHaveArgVersion = false; + bool bHaveArgVersionLong = false; + bool bHaveArgNoLog = false; + bool bHaveArgHelp = false; + +// Hardcode the use of the MI driver #if MICONFIG_DEFAULT_TO_MI_DRIVER - bHaveArgInterpret = true; + bHaveArgInterpret = true; #endif // MICONFIG_DEFAULT_TO_MI_DRIVER - if( bHaveArgs ) - { - // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING - for( MIint i = 1; i < argc; i++ ) - { - // *** Add args to help in GetHelpOnCmdLineArgOptions() *** - const CMIUtilString strArg( argv[ i ] ); - - // Argument "--executable" is also check for in CMIDriver::ParseArgs() - if( (0 == strArg.compare( "--interpreter" )) || // Given by the client such as Eclipse - (0 == strArg.compare( "--executable" )) ) // Used to specify that there is executable argument also on the command line - { // See fn description. - bHaveArgInterpret = true; - } - if( 0 == strArg.compare( "--version" ) ) - { - bHaveArgVersion = true; - } - if( 0 == strArg.compare( "--versionLong" ) ) - { - bHaveArgVersionLong = true; - } - if( 0 == strArg.compare( "--noLog" ) ) - { - bHaveArgNoLog = true; - } - if( (0 == strArg.compare( "--help" )) || (0 == strArg.compare( "-h" )) ) - { - bHaveArgHelp = true; - } - } - } - - if( bHaveArgNoLog ) - { - CMICmnLog::Instance().SetEnabled( false ); - } - - // Todo: Remove this output when MI is finished. It is temporary to persuade Ecllipse plugin to work. - // Eclipse reads this literally and will not work unless it gets this exact version text. - // Handle --version option (ignore the --interpreter option if present) - if( bHaveArgVersion ) - { - vwbExiting = true; - bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse( MIRSRC( IDE_MI_VERSION_GDB ) ); - return bOk; - } - - // Todo: Make this the --version when the the above --version version is removed - // Handle --versionlong option (ignore the --interpreter option if present) - if( bHaveArgVersionLong ) - { - vwbExiting = true; - bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse( GetAppVersion() ); - return bOk; - } - - // Both '--help' and '--intepreter' means give help for MI only. Without - // '--interpreter' help the LLDB driver is working and so help is for that. - if( bHaveArgHelp && bHaveArgInterpret ) - { - vwbExiting = true; - bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse( GetHelpOnCmdLineArgOptions() ); - return bOk; - } - - // This makes the assumption that there is at least one MI compatible - // driver registered and one LLDB driver registerd and the CMIDriver - // is the first one found. - // ToDo: Implement a better solution that handle any order, any number - // of drivers. Or this 'feature' may be removed if deemed not required. - IDriver * pLldbDriver = GetFirstNonMIDriver(); - IDriver * pMi2Driver = GetFirstMIDriver(); - if( bHaveArgInterpret && (pMi2Driver != nullptr) ) - bOk = bOk && SetUseThisDriverToDoWork( *pMi2Driver ); - else if( pLldbDriver != nullptr ) - bOk = bOk && SetUseThisDriverToDoWork( *pLldbDriver ); - else - { - if( bOk ) - { - vwbExiting = true; - const CMIUtilString msg( MIRSRC( IDS_DRIVER_ERR_NON_REGISTERED ) ); - bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse( msg ); - } - } - - return bOk; + if (bHaveArgs) + { + // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING + for (MIint i = 1; i < argc; i++) + { + // *** Add args to help in GetHelpOnCmdLineArgOptions() *** + const CMIUtilString strArg(argv[i]); + + // Argument "--executable" is also check for in CMIDriver::ParseArgs() + if ((0 == strArg.compare("--interpreter")) || // Given by the client such as Eclipse + (0 == strArg.compare("--executable"))) // Used to specify that there is executable argument also on the command line + { // See fn description. + bHaveArgInterpret = true; + } + if (0 == strArg.compare("--version")) + { + bHaveArgVersion = true; + } + if (0 == strArg.compare("--versionLong")) + { + bHaveArgVersionLong = true; + } + if (0 == strArg.compare("--noLog")) + { + bHaveArgNoLog = true; + } + if ((0 == strArg.compare("--help")) || (0 == strArg.compare("-h"))) + { + bHaveArgHelp = true; + } + } + } + + if (bHaveArgNoLog) + { + CMICmnLog::Instance().SetEnabled(false); + } + + // Todo: Remove this output when MI is finished. It is temporary to persuade Ecllipse plugin to work. + // Eclipse reads this literally and will not work unless it gets this exact version text. + // Handle --version option (ignore the --interpreter option if present) + if (bHaveArgVersion) + { + vwbExiting = true; + bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse(MIRSRC(IDE_MI_VERSION_GDB)); + return bOk; + } + + // Todo: Make this the --version when the the above --version version is removed + // Handle --versionlong option (ignore the --interpreter option if present) + if (bHaveArgVersionLong) + { + vwbExiting = true; + bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse(GetAppVersion()); + return bOk; + } + + // Both '--help' and '--intepreter' means give help for MI only. Without + // '--interpreter' help the LLDB driver is working and so help is for that. + if (bHaveArgHelp && bHaveArgInterpret) + { + vwbExiting = true; + bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse(GetHelpOnCmdLineArgOptions()); + return bOk; + } + + // This makes the assumption that there is at least one MI compatible + // driver registered and one LLDB driver registerd and the CMIDriver + // is the first one found. + // ToDo: Implement a better solution that handle any order, any number + // of drivers. Or this 'feature' may be removed if deemed not required. + IDriver *pLldbDriver = GetFirstNonMIDriver(); + IDriver *pMi2Driver = GetFirstMIDriver(); + if (bHaveArgInterpret && (pMi2Driver != nullptr)) + bOk = bOk && SetUseThisDriverToDoWork(*pMi2Driver); + else if (pLldbDriver != nullptr) + bOk = bOk && SetUseThisDriverToDoWork(*pLldbDriver); + else + { + if (bOk) + { + vwbExiting = true; + const CMIUtilString msg(MIRSRC(IDS_DRIVER_ERR_NON_REGISTERED)); + bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse(msg); + } + } + + return bOk; } - + //++ ------------------------------------------------------------------------------------ -// Details: Return formatted application version and name information. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Text data. -// Throws: None. +// Details: Return formatted application version and name information. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Text data. +// Throws: None. //-- -CMIUtilString CMIDriverMgr::GetAppVersion( void ) const +CMIUtilString +CMIDriverMgr::GetAppVersion(void) const { - const CMIUtilString strProj( MIRSRC( IDS_PROJNAME ) ); - const CMIUtilString strVsn( CMIDriver::Instance().GetVersionDescription() ); - const CMIUtilString strGdb( MIRSRC( IDE_MI_VERSION_GDB ) ); - const CMIUtilString strVrsnInfo( CMIUtilString::Format( "%s\n%s\n%s", strProj.c_str(), strVsn.c_str(), strGdb.c_str() ) ); + const CMIUtilString strProj(MIRSRC(IDS_PROJNAME)); + const CMIUtilString strVsn(CMIDriver::Instance().GetVersionDescription()); + const CMIUtilString strGdb(MIRSRC(IDE_MI_VERSION_GDB)); + const CMIUtilString strVrsnInfo(CMIUtilString::Format("%s\n%s\n%s", strProj.c_str(), strVsn.c_str(), strGdb.c_str())); - return strVrsnInfo; + return strVrsnInfo; } //++ ------------------------------------------------------------------------------------ -// Details: Return formatted help information on all the MI command line options. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Text data. -// Throws: None. +// Details: Return formatted help information on all the MI command line options. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Text data. +// Throws: None. //-- -CMIUtilString CMIDriverMgr::GetHelpOnCmdLineArgOptions( void ) const +CMIUtilString +CMIDriverMgr::GetHelpOnCmdLineArgOptions(void) const { - const CMIUtilString pHelp[] = - { - MIRSRC( IDE_MI_APP_DESCRIPTION ), - MIRSRC( IDE_MI_APP_INFORMATION ), - MIRSRC( IDE_MI_APP_ARG_USAGE ), - MIRSRC( IDE_MI_APP_ARG_HELP ), - MIRSRC( IDE_MI_APP_ARG_VERSION ), - MIRSRC( IDE_MI_APP_ARG_VERSION_LONG ), - MIRSRC( IDE_MI_APP_ARG_INTERPRETER ), - MIRSRC( IDE_MI_APP_ARG_EXECUTEABLE ), - CMIUtilString::Format( MIRSRC( IDE_MI_APP_ARG_NO_APP_LOG ), CMICmnLogMediumFile::Instance().GetFileName().c_str() ), - MIRSRC( IDE_MI_APP_ARG_EXECUTABLE ), - MIRSRC( IDS_CMD_QUIT_HELP ), - MIRSRC( IDE_MI_APP_ARG_EXAMPLE ) - }; - const MIuint nHelpItems = sizeof pHelp / sizeof pHelp[ 0 ]; - CMIUtilString strHelp; - for( MIuint i = 0; i < nHelpItems; i++ ) - { - strHelp += pHelp[ i ]; - strHelp += "\n\n"; - } - - return strHelp; + const CMIUtilString pHelp[] = { + MIRSRC(IDE_MI_APP_DESCRIPTION), + MIRSRC(IDE_MI_APP_INFORMATION), + MIRSRC(IDE_MI_APP_ARG_USAGE), + MIRSRC(IDE_MI_APP_ARG_HELP), + MIRSRC(IDE_MI_APP_ARG_VERSION), + MIRSRC(IDE_MI_APP_ARG_VERSION_LONG), + MIRSRC(IDE_MI_APP_ARG_INTERPRETER), + MIRSRC(IDE_MI_APP_ARG_EXECUTEABLE), + CMIUtilString::Format(MIRSRC(IDE_MI_APP_ARG_NO_APP_LOG), CMICmnLogMediumFile::Instance().GetFileName().c_str()), + MIRSRC(IDE_MI_APP_ARG_EXECUTABLE), + MIRSRC(IDS_CMD_QUIT_HELP), + MIRSRC(IDE_MI_APP_ARG_EXAMPLE)}; + const MIuint nHelpItems = sizeof pHelp / sizeof pHelp[0]; + CMIUtilString strHelp; + for (MIuint i = 0; i < nHelpItems; i++) + { + strHelp += pHelp[i]; + strHelp += "\n\n"; + } + + return strHelp; } //++ ------------------------------------------------------------------------------------ -// Details: Search the registered drivers and return the first driver which says it is -// GDB/MI compatible i.e. the CMIDriver class. -// Type: Method. -// Args: None. -// Return: IDriver * - Ptr to driver, NULL = no driver found. -// Throws: None. +// Details: Search the registered drivers and return the first driver which says it is +// GDB/MI compatible i.e. the CMIDriver class. +// Type: Method. +// Args: None. +// Return: IDriver * - Ptr to driver, NULL = no driver found. +// Throws: None. //-- -CMIDriverMgr::IDriver * CMIDriverMgr::GetFirstMIDriver( void ) const +CMIDriverMgr::IDriver * +CMIDriverMgr::GetFirstMIDriver(void) const { - IDriver * pDriver = nullptr; - MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); - while( it != m_mapDriverIdToDriver.end() ) - { - const CMIUtilString & rDrvId = (*it).first; MIunused( rDrvId ); - IDriver * pDvr = (*it).second; - if( pDvr->GetDriverIsGDBMICompatibleDriver() ) - { - pDriver = pDvr; - break; - } - - // Next - ++it; - } - - return pDriver; + IDriver *pDriver = nullptr; + MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); + while (it != m_mapDriverIdToDriver.end()) + { + const CMIUtilString &rDrvId = (*it).first; + MIunused(rDrvId); + IDriver *pDvr = (*it).second; + if (pDvr->GetDriverIsGDBMICompatibleDriver()) + { + pDriver = pDvr; + break; + } + + // Next + ++it; + } + + return pDriver; } //++ ------------------------------------------------------------------------------------ -// Details: Search the registered drivers and return the first driver which says it is -// not GDB/MI compatible i.e. the LLDB Driver class. -// Type: Method. -// Args: None. -// Return: IDriver * - Ptr to driver, NULL = no driver found. -// Throws: None. +// Details: Search the registered drivers and return the first driver which says it is +// not GDB/MI compatible i.e. the LLDB Driver class. +// Type: Method. +// Args: None. +// Return: IDriver * - Ptr to driver, NULL = no driver found. +// Throws: None. //-- -CMIDriverMgr::IDriver * CMIDriverMgr::GetFirstNonMIDriver( void ) const +CMIDriverMgr::IDriver * +CMIDriverMgr::GetFirstNonMIDriver(void) const { - IDriver * pDriver = nullptr; - MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); - while( it != m_mapDriverIdToDriver.end() ) - { - const CMIUtilString & rDrvId = (*it).first; MIunused( rDrvId ); - IDriver * pDvr = (*it).second; - if( !pDvr->GetDriverIsGDBMICompatibleDriver() ) - { - pDriver = pDvr; - break; - } - - // Next - ++it; - } - - return pDriver; + IDriver *pDriver = nullptr; + MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); + while (it != m_mapDriverIdToDriver.end()) + { + const CMIUtilString &rDrvId = (*it).first; + MIunused(rDrvId); + IDriver *pDvr = (*it).second; + if (!pDvr->GetDriverIsGDBMICompatibleDriver()) + { + pDriver = pDvr; + break; + } + + // Next + ++it; + } + + return pDriver; } //++ ------------------------------------------------------------------------------------ -// Details: Search the registered drivers and return driver with the specified ID. -// Type: Method. -// Args: vrDriverId - (R) ID of a driver. -// Return: IDriver * - Ptr to driver, NULL = no driver found. -// Throws: None. +// Details: Search the registered drivers and return driver with the specified ID. +// Type: Method. +// Args: vrDriverId - (R) ID of a driver. +// Return: IDriver * - Ptr to driver, NULL = no driver found. +// Throws: None. //-- -CMIDriverMgr::IDriver * CMIDriverMgr::GetDriver( const CMIUtilString & vrDriverId ) const +CMIDriverMgr::IDriver * +CMIDriverMgr::GetDriver(const CMIUtilString &vrDriverId) const { - MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.find( vrDriverId ); - if( it == m_mapDriverIdToDriver.end() ) - return nullptr; + MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.find(vrDriverId); + if (it == m_mapDriverIdToDriver.end()) + return nullptr; + + IDriver *pDriver = (*it).second; - IDriver * pDriver = (*it).second; - - return pDriver; + return pDriver; } - diff --git a/tools/lldb-mi/MIDriverMgr.h b/tools/lldb-mi/MIDriverMgr.h index 438d184895b1..d9449277b063 100644 --- a/tools/lldb-mi/MIDriverMgr.h +++ b/tools/lldb-mi/MIDriverMgr.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIDriverMgr.h +// File: MIDriverMgr.h // -// Overview: CMIImplCmn interface. +// Overview: CMIImplCmn interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadme.txt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadme.txt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -32,107 +32,106 @@ #include "MIUtilSingletonBase.h" //++ ============================================================================ -// Details: MI Driver Manager. Register lldb::SBBroadcaster derived Driver type -// objects with *this manager. The manager does not own driver objects -// registered with it and so will not delete when this manager is -// shutdown. The Driver flagged as "use this one" will be set as current -// driver and will be the one that is used. Other drivers are not -// operated. A Driver can call another Driver should it not handle a -// command. -// It also initializes other resources as part it's setup such as the -// Logger and Resources objects (explicit indicate *this object requires -// those objects (modules/components) to support it's own functionality). -// The Driver manager is the first object instantiated as part of the -// MI code base. It is also the first thing to interpret the command -// line arguments passed to the executeable. Bases on options it -// understands the manage will set up the appropriate driver or give -// help information. Other options are passed on to the driver chosen -// to do work. -// Each driver instance (the CMIDriver, LLDB::Driver) has its own -// LLDB::SBDebugger. -// Singleton class. -// Gotchas: None. -// Authors: Illya Rudkin 28/02/2014. -// Changes: None. +// Details: MI Driver Manager. Register lldb::SBBroadcaster derived Driver type +// objects with *this manager. The manager does not own driver objects +// registered with it and so will not delete when this manager is +// shutdown. The Driver flagged as "use this one" will be set as current +// driver and will be the one that is used. Other drivers are not +// operated. A Driver can call another Driver should it not handle a +// command. +// It also initializes other resources as part it's setup such as the +// Logger and Resources objects (explicit indicate *this object requires +// those objects (modules/components) to support it's own functionality). +// The Driver manager is the first object instantiated as part of the +// MI code base. It is also the first thing to interpret the command +// line arguments passed to the executeable. Bases on options it +// understands the manage will set up the appropriate driver or give +// help information. Other options are passed on to the driver chosen +// to do work. +// Each driver instance (the CMIDriver, LLDB::Driver) has its own +// LLDB::SBDebugger. +// Singleton class. +// Gotchas: None. +// Authors: Illya Rudkin 28/02/2014. +// Changes: None. //-- -class CMIDriverMgr -: public CMICmnBase -, public MI::ISingleton< CMIDriverMgr > +class CMIDriverMgr : public CMICmnBase, public MI::ISingleton { - friend MI::ISingleton< CMIDriverMgr >; + friend MI::ISingleton; -// Class: -public: - //++ - // Description: Driver deriver objects need this interface to work with - // *this manager. - //-- - class IDriver - { - public: - virtual bool DoInitialize( void ) = 0; - virtual bool DoShutdown( void ) = 0; - virtual bool DoMainLoop( void ) = 0; - virtual void DoResizeWindow( const uint32_t vWindowSizeWsCol ) = 0; - virtual lldb::SBError DoParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting ) = 0; - virtual CMIUtilString GetError( void ) const = 0; - virtual const CMIUtilString & GetName( void ) const = 0; - virtual lldb::SBDebugger & GetTheDebugger( void ) = 0; - virtual bool GetDriverIsGDBMICompatibleDriver( void ) const = 0; - virtual bool SetId( const CMIUtilString & vId ) = 0; - virtual const CMIUtilString & GetId( void ) const = 0; + // Class: + public: + //++ + // Description: Driver deriver objects need this interface to work with + // *this manager. + //-- + class IDriver + { + public: + virtual bool DoInitialize(void) = 0; + virtual bool DoShutdown(void) = 0; + virtual bool DoMainLoop(void) = 0; + virtual void DoResizeWindow(const uint32_t vWindowSizeWsCol) = 0; + virtual lldb::SBError DoParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting) = 0; + virtual CMIUtilString GetError(void) const = 0; + virtual const CMIUtilString &GetName(void) const = 0; + virtual lldb::SBDebugger &GetTheDebugger(void) = 0; + virtual bool GetDriverIsGDBMICompatibleDriver(void) const = 0; + virtual bool SetId(const CMIUtilString &vId) = 0; + virtual const CMIUtilString &GetId(void) const = 0; - // Not part of the interface, ignore - /* dtor */ virtual ~IDriver( void ) {} - }; - -// Methods: -public: - // MI system - bool Initialize( void ); - bool Shutdown( void ); - // - CMIUtilString GetAppVersion( void ) const; - bool RegisterDriver( const IDriver & vrADriver, const CMIUtilString & vrDriverID ); - bool UnregisterDriver( const IDriver & vrADriver ); - bool SetUseThisDriverToDoWork( const IDriver & vrADriver ); // Specify working main driver - IDriver * GetUseThisDriverToDoWork( void ) const; - bool ParseArgs( const int argc, const char * argv[], bool & vwbExiting ); - IDriver * GetDriver( const CMIUtilString & vrDriverId ) const; - // - // MI Proxy fn to current specified working driver - bool DriverMainLoop( void ); - void DriverResizeWindow( const uint32_t vWindowSizeWsCol ); - bool DriverParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting ); - CMIUtilString DriverGetError( void ) const; - CMIUtilString DriverGetName( void ) const; - lldb::SBDebugger * DriverGetTheDebugger( void ); + // Not part of the interface, ignore + /* dtor */ virtual ~IDriver(void) {} + }; -// Typedef: -private: - typedef std::map< CMIUtilString, IDriver * > MapDriverIdToDriver_t; - typedef std::pair< CMIUtilString, IDriver * > MapPairDriverIdToDriver_t; + // Methods: + public: + // MI system + bool Initialize(void); + bool Shutdown(void); + // + CMIUtilString GetAppVersion(void) const; + bool RegisterDriver(const IDriver &vrADriver, const CMIUtilString &vrDriverID); + bool UnregisterDriver(const IDriver &vrADriver); + bool + SetUseThisDriverToDoWork(const IDriver &vrADriver); // Specify working main driver + IDriver *GetUseThisDriverToDoWork(void) const; + bool ParseArgs(const int argc, const char *argv[], bool &vwbExiting); + IDriver *GetDriver(const CMIUtilString &vrDriverId) const; + // + // MI Proxy fn to current specified working driver + bool DriverMainLoop(void); + void DriverResizeWindow(const uint32_t vWindowSizeWsCol); + bool DriverParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting); + CMIUtilString DriverGetError(void) const; + CMIUtilString DriverGetName(void) const; + lldb::SBDebugger *DriverGetTheDebugger(void); -// Methods: -private: - /* ctor */ CMIDriverMgr( void ); - /* ctor */ CMIDriverMgr( const CMIDriverMgr & ); - void operator=( const CMIDriverMgr & ); - // - bool HaveDriverAlready( const IDriver & vrMedium ) const; - bool UnregisterDriverAll( void ); - IDriver * GetFirstMIDriver( void ) const; - IDriver * GetFirstNonMIDriver( void ) const; - CMIUtilString GetHelpOnCmdLineArgOptions( void ) const; + // Typedef: + private: + typedef std::map MapDriverIdToDriver_t; + typedef std::pair MapPairDriverIdToDriver_t; -// Overridden: -private: - // From CMICmnBase - /* dtor */ virtual ~CMIDriverMgr( void ); + // Methods: + private: + /* ctor */ CMIDriverMgr(void); + /* ctor */ CMIDriverMgr(const CMIDriverMgr &); + void operator=(const CMIDriverMgr &); + // + bool HaveDriverAlready(const IDriver &vrMedium) const; + bool UnregisterDriverAll(void); + IDriver *GetFirstMIDriver(void) const; + IDriver *GetFirstNonMIDriver(void) const; + CMIUtilString GetHelpOnCmdLineArgOptions(void) const; -// Attributes: -private: - MapDriverIdToDriver_t m_mapDriverIdToDriver; - IDriver * m_pDriverCurrent; // This driver is used by this manager to do work. It is the main driver. - bool m_bInMi2Mode; // True = --interpreter entered on the cmd line, false = operate LLDB driver (non GDB) + // Overridden: + private: + // From CMICmnBase + /* dtor */ virtual ~CMIDriverMgr(void); + + // Attributes: + private: + MapDriverIdToDriver_t m_mapDriverIdToDriver; + IDriver *m_pDriverCurrent; // This driver is used by this manager to do work. It is the main driver. + bool m_bInMi2Mode; // True = --interpreter entered on the cmd line, false = operate LLDB driver (non GDB) }; diff --git a/tools/lldb-mi/MIUtilDateTimeStd.cpp b/tools/lldb-mi/MIUtilDateTimeStd.cpp index 9938deb131cc..bb9e238843e0 100644 --- a/tools/lldb-mi/MIUtilDateTimeStd.cpp +++ b/tools/lldb-mi/MIUtilDateTimeStd.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilDateTimeStd.cpp +// File: MIUtilDateTimeStd.cpp // -// Overview: CMIUtilDateTimeStd implementation. +// Overview: CMIUtilDateTimeStd implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: @@ -24,61 +24,62 @@ #include "MICmnResources.h" //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilDateTimeStd constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilDateTimeStd constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilDateTimeStd::CMIUtilDateTimeStd( void ) +CMIUtilDateTimeStd::CMIUtilDateTimeStd(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilDateTimeStd destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilDateTimeStd destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilDateTimeStd::~CMIUtilDateTimeStd( void ) +CMIUtilDateTimeStd::~CMIUtilDateTimeStd(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve system local current date. Format is MM/DD/YYYY. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Text description. -// Throws: None. +// Details: Retrieve system local current date. Format is MM/DD/YYYY. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Text description. +// Throws: None. //-- -CMIUtilString CMIUtilDateTimeStd::GetDate( void ) +CMIUtilString +CMIUtilDateTimeStd::GetDate(void) { - CMIUtilString strDate( MIRSRC( IDS_WORD_INVALIDBRKTS ) ); - - std::time( &m_rawTime ); - const std::tm * pTi = std::localtime( &m_rawTime ); - if( std::strftime( &m_pScratch[ 0 ], sizeof( m_pScratch ), "%d/%m/%y", pTi ) > 0 ) - strDate = m_pScratch; + CMIUtilString strDate(MIRSRC(IDS_WORD_INVALIDBRKTS)); - return strDate; + std::time(&m_rawTime); + const std::tm *pTi = std::localtime(&m_rawTime); + if (std::strftime(&m_pScratch[0], sizeof(m_pScratch), "%d/%m/%y", pTi) > 0) + strDate = m_pScratch; + + return strDate; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve system local current time. Format is HH:MM:SS 24 hour clock. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Text description. -// Throws: None. +// Details: Retrieve system local current time. Format is HH:MM:SS 24 hour clock. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Text description. +// Throws: None. //-- -CMIUtilString CMIUtilDateTimeStd::GetTime( void ) +CMIUtilString +CMIUtilDateTimeStd::GetTime(void) { - std::time( &m_rawTime ); - const std::tm * pTi = std::localtime( &m_rawTime ); - const CMIUtilString seconds( CMIUtilString::Format( "%d", pTi->tm_sec ) ); - const CMIUtilString zero( (seconds.length() == 1) ? "0" : "" ); - const CMIUtilString strTime( CMIUtilString::Format( "%d:%d:%s%s", pTi->tm_hour, pTi->tm_min, zero.c_str(), seconds.c_str() ) ); + std::time(&m_rawTime); + const std::tm *pTi = std::localtime(&m_rawTime); + const CMIUtilString seconds(CMIUtilString::Format("%d", pTi->tm_sec)); + const CMIUtilString zero((seconds.length() == 1) ? "0" : ""); + const CMIUtilString strTime(CMIUtilString::Format("%d:%d:%s%s", pTi->tm_hour, pTi->tm_min, zero.c_str(), seconds.c_str())); - return strTime; + return strTime; } - diff --git a/tools/lldb-mi/MIUtilDateTimeStd.h b/tools/lldb-mi/MIUtilDateTimeStd.h index da857d6358ee..1d9a1dac7dc6 100644 --- a/tools/lldb-mi/MIUtilDateTimeStd.h +++ b/tools/lldb-mi/MIUtilDateTimeStd.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilDateTimeStd.h +// File: MIUtilDateTimeStd.h // -// Overview: CMIUtilDateTimeStd interface. +// Overview: CMIUtilDateTimeStd interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -25,31 +25,31 @@ #include // In-house headers: -#include "MIUtilString.h" +#include "MIUtilString.h" //++ ============================================================================ -// Details: MI common code utility class. Used to retrieve system local date -// time. -// Gotchas: None. -// Authors: Illya Rudkin 16/07/2014. -// Changes: None. +// Details: MI common code utility class. Used to retrieve system local date +// time. +// Gotchas: None. +// Authors: Illya Rudkin 16/07/2014. +// Changes: None. //-- class CMIUtilDateTimeStd { -// Methods: -public: - /* ctor */ CMIUtilDateTimeStd( void ); - - CMIUtilString GetDate( void ); - CMIUtilString GetTime( void ); - -// Overrideable: -public: - // From CMICmnBase - /* dtor */ virtual ~CMIUtilDateTimeStd( void ); - -// Attributes: -private: - std::time_t m_rawTime; - MIchar m_pScratch[ 16 ]; + // Methods: + public: + /* ctor */ CMIUtilDateTimeStd(void); + + CMIUtilString GetDate(void); + CMIUtilString GetTime(void); + + // Overrideable: + public: + // From CMICmnBase + /* dtor */ virtual ~CMIUtilDateTimeStd(void); + + // Attributes: + private: + std::time_t m_rawTime; + MIchar m_pScratch[16]; }; diff --git a/tools/lldb-mi/MIUtilDebug.cpp b/tools/lldb-mi/MIUtilDebug.cpp index 754920880ec4..c78506221b44 100644 --- a/tools/lldb-mi/MIUtilDebug.cpp +++ b/tools/lldb-mi/MIUtilDebug.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilDebug.h +// File: MIUtilDebug.h // -// Overview: Terminal setting termios functions. +// Overview: Terminal setting termios functions. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third party headers: @@ -30,65 +30,67 @@ #include "MICmnLog.h" //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilDebug constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilDebug constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilDebug::CMIUtilDebug( void ) +CMIUtilDebug::CMIUtilDebug(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilDebug destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilDebug destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilDebug::~CMIUtilDebug( void ) +CMIUtilDebug::~CMIUtilDebug(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Show a dialog to the process/application halts. It gives the opportunity to -// attach a debugger. -// Type: Static method. -// Args: None. -// Return: None. -// Throws: None. +// Details: Show a dialog to the process/application halts. It gives the opportunity to +// attach a debugger. +// Type: Static method. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMIUtilDebug::ShowDlgWaitForDbgAttach( void ) +void +CMIUtilDebug::ShowDlgWaitForDbgAttach(void) { - const CMIUtilString strCaption( CMIDriver::Instance().GetAppNameShort() ); + const CMIUtilString strCaption(CMIDriver::Instance().GetAppNameShort()); #ifdef _WIN32 - ::MessageBoxA( NULL, "Attach your debugger now", strCaption.c_str(), MB_OK ); + ::MessageBoxA(NULL, "Attach your debugger now", strCaption.c_str(), MB_OK); #else - // ToDo: Implement other platform version of an Ok to continue dialog box +// ToDo: Implement other platform version of an Ok to continue dialog box #endif // _WIN32 } //++ ------------------------------------------------------------------------------------ -// Details: Temporarily stall the process/application to give the programmer the -// opportunity to attach a debugger. How to use: Put a break in the programmer -// where you want to visit, run the application then attach your debugger to the -// application. Hit the debugger's pause button and the debugger should should -// show this loop. Change the i variable value to break out of the loop and -// visit your break point. -// Type: Static method. -// Args: None. -// Return: None. -// Throws: None. +// Details: Temporarily stall the process/application to give the programmer the +// opportunity to attach a debugger. How to use: Put a break in the programmer +// where you want to visit, run the application then attach your debugger to the +// application. Hit the debugger's pause button and the debugger should should +// show this loop. Change the i variable value to break out of the loop and +// visit your break point. +// Type: Static method. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMIUtilDebug::WaitForDbgAttachInfinteLoop( void ) +void +CMIUtilDebug::WaitForDbgAttachInfinteLoop(void) { - MIuint i = 0; - while( i == 0 ) - { - const std::chrono::milliseconds time( 100 ); - std::this_thread::sleep_for( time ); - } + MIuint i = 0; + while (i == 0) + { + const std::chrono::milliseconds time(100); + std::this_thread::sleep_for(time); + } } //--------------------------------------------------------------------------------------- @@ -96,33 +98,32 @@ void CMIUtilDebug::WaitForDbgAttachInfinteLoop( void ) //--------------------------------------------------------------------------------------- // Instantiations: -CMICmnLog & CMIUtilDebugFnTrace::ms_rLog = CMICmnLog::Instance(); -MIuint CMIUtilDebugFnTrace::ms_fnDepthCnt = 0; +CMICmnLog &CMIUtilDebugFnTrace::ms_rLog = CMICmnLog::Instance(); +MIuint CMIUtilDebugFnTrace::ms_fnDepthCnt = 0; //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilDebugFnTrace constructor. -// Type: Method. -// Args: vFnName - (R) The text to insert into the log. -// Return: None. -// Throws: None. +// Details: CMIUtilDebugFnTrace constructor. +// Type: Method. +// Args: vFnName - (R) The text to insert into the log. +// Return: None. +// Throws: None. //-- -CMIUtilDebugFnTrace::CMIUtilDebugFnTrace( const CMIUtilString & vFnName ) -: m_strFnName( vFnName ) +CMIUtilDebugFnTrace::CMIUtilDebugFnTrace(const CMIUtilString &vFnName) + : m_strFnName(vFnName) { - const CMIUtilString txt( CMIUtilString::Format( "%d>%s", ++ms_fnDepthCnt, m_strFnName.c_str() ) ); - ms_rLog.Write( txt, CMICmnLog::eLogVerbosity_FnTrace ); + const CMIUtilString txt(CMIUtilString::Format("%d>%s", ++ms_fnDepthCnt, m_strFnName.c_str())); + ms_rLog.Write(txt, CMICmnLog::eLogVerbosity_FnTrace); } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilDebugFnTrace destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilDebugFnTrace destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilDebugFnTrace::~CMIUtilDebugFnTrace( void ) +CMIUtilDebugFnTrace::~CMIUtilDebugFnTrace(void) { - const CMIUtilString txt( CMIUtilString::Format( "%d<%s", ms_fnDepthCnt--, m_strFnName.c_str() ) ); - ms_rLog.Write( txt, CMICmnLog::eLogVerbosity_FnTrace ); + const CMIUtilString txt(CMIUtilString::Format("%d<%s", ms_fnDepthCnt--, m_strFnName.c_str())); + ms_rLog.Write(txt, CMICmnLog::eLogVerbosity_FnTrace); } - diff --git a/tools/lldb-mi/MIUtilDebug.h b/tools/lldb-mi/MIUtilDebug.h index b163b05f5de5..d643f73ba97e 100644 --- a/tools/lldb-mi/MIUtilDebug.h +++ b/tools/lldb-mi/MIUtilDebug.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilDebug.h +// File: MIUtilDebug.h // -// Overview: CMIUtilDebug interface. +// Overview: CMIUtilDebug interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -30,67 +30,67 @@ class CMICmnLog; //++ ============================================================================ -// Details: MI debugging aid utility class. -// Gotchas: None. -// Authors: -// Changes: None. +// Details: MI debugging aid utility class. +// Gotchas: None. +// Authors: +// Changes: None. //-- -class CMIUtilDebug +class CMIUtilDebug { -// Statics: -public: - static void ShowDlgWaitForDbgAttach( void ); - static void WaitForDbgAttachInfinteLoop( void ); - -// Methods: -public: - /* ctor */ CMIUtilDebug( void ); + // Statics: + public: + static void ShowDlgWaitForDbgAttach(void); + static void WaitForDbgAttachInfinteLoop(void); -// Overrideable: -public: - // From CMICmnBase - /* dtor */ virtual ~CMIUtilDebug( void ); + // Methods: + public: + /* ctor */ CMIUtilDebug(void); + + // Overrideable: + public: + // From CMICmnBase + /* dtor */ virtual ~CMIUtilDebug(void); }; //++ ============================================================================ -// Details: MI debug utility class. Used to indicate the current function -// depth in the call stack. It uses the CMIlCmnLog logger to output -// the current fn trace information. -// Use macro MI_TRACEFN( "Some fn name" ) and implement the scope of -// the functions you wish to build up a trace off. -// Use preprocessor definition MI_USE_DEBUG_TRACE_FN to turn off or on -// tracing code. -// Gotchas: None. -// Authors: Illya Rudkin 07/03/2014. -// Changes: None. +// Details: MI debug utility class. Used to indicate the current function +// depth in the call stack. It uses the CMIlCmnLog logger to output +// the current fn trace information. +// Use macro MI_TRACEFN( "Some fn name" ) and implement the scope of +// the functions you wish to build up a trace off. +// Use preprocessor definition MI_USE_DEBUG_TRACE_FN to turn off or on +// tracing code. +// Gotchas: None. +// Authors: Illya Rudkin 07/03/2014. +// Changes: None. //-- class CMIUtilDebugFnTrace { -// Methods: -public: - /* ctor */ CMIUtilDebugFnTrace( const CMIUtilString & vFnName ); + // Methods: + public: + /* ctor */ CMIUtilDebugFnTrace(const CMIUtilString &vFnName); + + // Overrideable: + public: + // From CMICmnBase + /* dtor */ virtual ~CMIUtilDebugFnTrace(void); -// Overrideable: -public: - // From CMICmnBase - /* dtor */ virtual ~CMIUtilDebugFnTrace( void ); + // Attributes: + private: + const CMIUtilString m_strFnName; -// Attributes: -private: - const CMIUtilString m_strFnName; - - static CMICmnLog & ms_rLog; - static MIuint ms_fnDepthCnt; // Increment count as fn depth increases, decrement count as fn stack pops off + static CMICmnLog &ms_rLog; + static MIuint ms_fnDepthCnt; // Increment count as fn depth increases, decrement count as fn stack pops off }; //++ ============================================================================ -// Details: Take the given text and send it to the server's Logger to output to the -// trace file. -// Type: Compile preprocess. -// Args: x - (R) Message (may be seen by user). +// Details: Take the given text and send it to the server's Logger to output to the +// trace file. +// Type: Compile preprocess. +// Args: x - (R) Message (may be seen by user). //-- #ifdef MI_USE_DEBUG_TRACE_FN -#define MI_TRACEFN( x ) CMIUtilDebugFnTrace __MITrace( x ) +#define MI_TRACEFN(x) CMIUtilDebugFnTrace __MITrace(x) #else -#define MI_TRACEFN( x ) +#define MI_TRACEFN(x) #endif // MI_USE_DEBUG_TRACE_FN diff --git a/tools/lldb-mi/MIUtilFileStd.cpp b/tools/lldb-mi/MIUtilFileStd.cpp index 853fd7455680..dc5ea6cb32ff 100644 --- a/tools/lldb-mi/MIUtilFileStd.cpp +++ b/tools/lldb-mi/MIUtilFileStd.cpp @@ -8,21 +8,21 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilFileStd.cpp +// File: MIUtilFileStd.cpp // -// Overview: CMIUtilFileStd implementation. +// Overview: CMIUtilFileStd implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third party headers #include #include -#include // For strerror() +#include // For strerror() #include // In-house headers: @@ -30,261 +30,270 @@ #include "MICmnResources.h" //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilFileStd constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilFileStd constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilFileStd::CMIUtilFileStd( void ) -: m_fileNamePath( CMIUtilString() ) -, m_pFileHandle( nullptr ) -#if defined( _MSC_VER ) -, m_constCharNewLine( "\r\n" ) +CMIUtilFileStd::CMIUtilFileStd(void) + : m_fileNamePath(CMIUtilString()) + , m_pFileHandle(nullptr) +#if defined(_MSC_VER) + , m_constCharNewLine("\r\n") #else -, m_constCharNewLine( "\n" ) + , m_constCharNewLine("\n") #endif // #if defined( _MSC_VER ) -, m_bFileError( false ) + , m_bFileError(false) { } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilFileStd destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilFileStd destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilFileStd::~CMIUtilFileStd( void ) +CMIUtilFileStd::~CMIUtilFileStd(void) { - Close(); + Close(); } //++ ------------------------------------------------------------------------------------ -// Details: Open file for writing. On the first call to this function after *this object -// is created the file is either created or replace, from then on open only opens -// an existing file. -// Type: Method. -// Args: vFileNamePath - (R) File name path. -// vwrbNewCreated - (W) True - file recreated, false - file appended too. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Open file for writing. On the first call to this function after *this object +// is created the file is either created or replace, from then on open only opens +// an existing file. +// Type: Method. +// Args: vFileNamePath - (R) File name path. +// vwrbNewCreated - (W) True - file recreated, false - file appended too. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilFileStd::CreateWrite( const CMIUtilString & vFileNamePath, bool & vwrbNewCreated ) +bool +CMIUtilFileStd::CreateWrite(const CMIUtilString &vFileNamePath, bool &vwrbNewCreated) { - // Reset - m_bFileError = false; - vwrbNewCreated = false; - - if( vFileNamePath.empty() ) - { - m_bFileError = true; - SetErrorDescription( MIRSRC( IDS_UTIL_FILE_ERR_INVALID_PATHNAME ) ); - return MIstatus::failure; - } - - // File is already open so exit - if( m_pFileHandle != nullptr ) - return MIstatus::success; - -#if !defined( _MSC_VER ) - // Open with 'write' and 'binary' mode - m_pFileHandle = ::fopen( vFileNamePath.c_str(), "wb" ); + // Reset + m_bFileError = false; + vwrbNewCreated = false; + + if (vFileNamePath.empty()) + { + m_bFileError = true; + SetErrorDescription(MIRSRC(IDS_UTIL_FILE_ERR_INVALID_PATHNAME)); + return MIstatus::failure; + } + + // File is already open so exit + if (m_pFileHandle != nullptr) + return MIstatus::success; + +#if !defined(_MSC_VER) + // Open with 'write' and 'binary' mode + m_pFileHandle = ::fopen(vFileNamePath.c_str(), "wb"); #else - // Open a file with exclusive write and shared read permissions - m_pFileHandle = ::_fsopen( vFileNamePath.c_str(), "wb", _SH_DENYWR ); + // Open a file with exclusive write and shared read permissions + m_pFileHandle = ::_fsopen(vFileNamePath.c_str(), "wb", _SH_DENYWR); #endif // !defined( _MSC_VER ) - if( m_pFileHandle == nullptr ) - { - m_bFileError = true; - SetErrorDescriptionn( MIRSRC( IDS_UTIL_FILE_ERR_OPENING_FILE ), strerror( errno ), vFileNamePath.c_str() ); - return MIstatus::failure; - } - - vwrbNewCreated = true; - m_fileNamePath = vFileNamePath; - - return MIstatus::success; + if (m_pFileHandle == nullptr) + { + m_bFileError = true; + SetErrorDescriptionn(MIRSRC(IDS_UTIL_FILE_ERR_OPENING_FILE), strerror(errno), vFileNamePath.c_str()); + return MIstatus::failure; + } + + vwrbNewCreated = true; + m_fileNamePath = vFileNamePath; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Write data to existing opened file. -// Type: Method. -// Args: vData - (R) Text data. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Write data to existing opened file. +// Type: Method. +// Args: vData - (R) Text data. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilFileStd::Write( const CMIUtilString & vData ) +bool +CMIUtilFileStd::Write(const CMIUtilString &vData) { - if( vData.size() == 0 ) - return MIstatus::success; - - if( m_bFileError ) - return MIstatus::failure; - - if( m_pFileHandle == nullptr ) - { - m_bFileError = true; - SetErrorDescriptionn( MIRSRC( IDE_UTIL_FILE_ERR_WRITING_NOTOPEN ), m_fileNamePath.c_str() ); - return MIstatus::failure; - } - - // Get the string size - MIuint size = vData.size(); - if( ::fwrite( vData.c_str(), 1, size, m_pFileHandle ) == size ) - { - // Flush the data to the file - ::fflush( m_pFileHandle ); - return MIstatus::success; - } - - // Not all of the data has been transferred - m_bFileError = true; - SetErrorDescriptionn( MIRSRC( IDE_UTIL_FILE_ERR_WRITING_FILE ), m_fileNamePath.c_str() ); - return MIstatus::failure; + if (vData.size() == 0) + return MIstatus::success; + + if (m_bFileError) + return MIstatus::failure; + + if (m_pFileHandle == nullptr) + { + m_bFileError = true; + SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_NOTOPEN), m_fileNamePath.c_str()); + return MIstatus::failure; + } + + // Get the string size + MIuint size = vData.size(); + if (::fwrite(vData.c_str(), 1, size, m_pFileHandle) == size) + { + // Flush the data to the file + ::fflush(m_pFileHandle); + return MIstatus::success; + } + + // Not all of the data has been transferred + m_bFileError = true; + SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_FILE), m_fileNamePath.c_str()); + return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ -// Details: Write data to existing opened file. -// Type: Method. -// Args: vData - (R) Text data. -// vCharCnt - (R) Text data length. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Write data to existing opened file. +// Type: Method. +// Args: vData - (R) Text data. +// vCharCnt - (R) Text data length. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilFileStd::Write( const MIchar * vpData, const MIuint vCharCnt ) +bool +CMIUtilFileStd::Write(const MIchar *vpData, const MIuint vCharCnt) { - if( vCharCnt == 0 ) - return MIstatus::success; - - if( m_bFileError ) - return MIstatus::failure; - - if( m_pFileHandle == nullptr ) - { - m_bFileError = true; - SetErrorDescriptionn( MIRSRC( IDE_UTIL_FILE_ERR_WRITING_NOTOPEN ), m_fileNamePath.c_str() ); - return MIstatus::failure; - } - - if( ::fwrite( vpData, 1, vCharCnt, m_pFileHandle ) == vCharCnt ) - { - // Flush the data to the file - ::fflush( m_pFileHandle ); - return MIstatus::success; - } - - // Not all of the data has been transferred - m_bFileError = true; - SetErrorDescriptionn( MIRSRC( IDE_UTIL_FILE_ERR_WRITING_FILE ), m_fileNamePath.c_str() ); - return MIstatus::failure; + if (vCharCnt == 0) + return MIstatus::success; + + if (m_bFileError) + return MIstatus::failure; + + if (m_pFileHandle == nullptr) + { + m_bFileError = true; + SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_NOTOPEN), m_fileNamePath.c_str()); + return MIstatus::failure; + } + + if (::fwrite(vpData, 1, vCharCnt, m_pFileHandle) == vCharCnt) + { + // Flush the data to the file + ::fflush(m_pFileHandle); + return MIstatus::success; + } + + // Not all of the data has been transferred + m_bFileError = true; + SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_FILE), m_fileNamePath.c_str()); + return MIstatus::failure; } - + //++ ------------------------------------------------------------------------------------ -// Details: Close existing opened file. Note Close() must must an open! -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: Close existing opened file. Note Close() must must an open! +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMIUtilFileStd::Close( void ) +void +CMIUtilFileStd::Close(void) { - if( m_pFileHandle == nullptr ) - return; - - ::fclose( m_pFileHandle ); - m_pFileHandle = nullptr; - //m_bFileError = false; Do not reset as want to remain until next attempt at open or create + if (m_pFileHandle == nullptr) + return; + + ::fclose(m_pFileHandle); + m_pFileHandle = nullptr; + // m_bFileError = false; Do not reset as want to remain until next attempt at open or create } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve state of whether the file is ok. -// Type: Method. -// Args: None. -// Return: True - file ok. -// False - file has a problem. -// Throws: None. +// Details: Retrieve state of whether the file is ok. +// Type: Method. +// Args: None. +// Return: True - file ok. +// False - file has a problem. +// Throws: None. //-- -bool CMIUtilFileStd::IsOk( void ) const +bool +CMIUtilFileStd::IsOk(void) const { - return !m_bFileError; + return !m_bFileError; } //++ ------------------------------------------------------------------------------------ -// Details: Status on a file existing already. -// Type: Method. -// Args: vFileNamePath. -// Return: True - Exists. -// False - Not found. -// Throws: None. +// Details: Status on a file existing already. +// Type: Method. +// Args: vFileNamePath. +// Return: True - Exists. +// False - Not found. +// Throws: None. //-- -bool CMIUtilFileStd::IsFileExist( const CMIUtilString & vFileNamePath ) const +bool +CMIUtilFileStd::IsFileExist(const CMIUtilString &vFileNamePath) const { - if( vFileNamePath.empty() ) - return false; - - FILE * pTmp = nullptr; - pTmp = ::fopen( vFileNamePath.c_str(), "wb" ); - if( pTmp != nullptr ) - { - ::fclose( pTmp ); - return true; - } - - return false; + if (vFileNamePath.empty()) + return false; + + FILE *pTmp = nullptr; + pTmp = ::fopen(vFileNamePath.c_str(), "wb"); + if (pTmp != nullptr) + { + ::fclose(pTmp); + return true; + } + + return false; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the file current carriage line return characters used. -// Type: Method. -// Args: None. -// Return: CMIUtilString & - Text. -// Throws: None. +// Details: Retrieve the file current carriage line return characters used. +// Type: Method. +// Args: None. +// Return: CMIUtilString & - Text. +// Throws: None. //-- -const CMIUtilString & CMIUtilFileStd::GetLineReturn( void ) const +const CMIUtilString & +CMIUtilFileStd::GetLineReturn(void) const { - return m_constCharNewLine; + return m_constCharNewLine; } //++ ------------------------------------------------------------------------------------ -// Details: Given a file name directory path, strip off the filename and return the path. -// It look for either backslash or forward slash. -// Type: Method. -// Args: vDirectoryPath - (R) Text directory path. -// Return: CMIUtilString - Directory path. -// Throws: None. +// Details: Given a file name directory path, strip off the filename and return the path. +// It look for either backslash or forward slash. +// Type: Method. +// Args: vDirectoryPath - (R) Text directory path. +// Return: CMIUtilString - Directory path. +// Throws: None. //-- -CMIUtilString CMIUtilFileStd::StripOffFileName( const CMIUtilString & vDirectoryPath ) const +CMIUtilString +CMIUtilFileStd::StripOffFileName(const CMIUtilString &vDirectoryPath) const { - const MIint nPos = vDirectoryPath.rfind( '\\' ); - MIint nPos2 = vDirectoryPath.rfind( '/' ); - if( (nPos == (MIint) std::string::npos) && (nPos2 == (MIint) std::string::npos) ) - return vDirectoryPath; + const MIint nPos = vDirectoryPath.rfind('\\'); + MIint nPos2 = vDirectoryPath.rfind('/'); + if ((nPos == (MIint)std::string::npos) && (nPos2 == (MIint)std::string::npos)) + return vDirectoryPath; - if( nPos > nPos2 ) - nPos2 = nPos; + if (nPos > nPos2) + nPos2 = nPos; - const CMIUtilString strPath( vDirectoryPath.substr( 0, nPos2 ).c_str() ); - return strPath; + const CMIUtilString strPath(vDirectoryPath.substr(0, nPos2).c_str()); + return strPath; } //++ ------------------------------------------------------------------------------------ -// Details: Return either backslash or forward slash appropriate to the OS this applilcation -// is running on. -// Type: Static method. -// Args: None. -// Return: MIchar - '/' or '\' character. -// Throws: None. +// Details: Return either backslash or forward slash appropriate to the OS this applilcation +// is running on. +// Type: Static method. +// Args: None. +// Return: MIchar - '/' or '\' character. +// Throws: None. //-- -MIchar CMIUtilFileStd::GetSlash( void ) +MIchar +CMIUtilFileStd::GetSlash(void) { -#if !defined( _MSC_VER ) - return '/'; +#if !defined(_MSC_VER) + return '/'; #else - return '\\'; + return '\\'; #endif // !defined( _MSC_VER ) } diff --git a/tools/lldb-mi/MIUtilFileStd.h b/tools/lldb-mi/MIUtilFileStd.h index b6655b2ecfe9..29537771265e 100644 --- a/tools/lldb-mi/MIUtilFileStd.h +++ b/tools/lldb-mi/MIUtilFileStd.h @@ -8,58 +8,57 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilFileStd.h +// File: MIUtilFileStd.h // -// Overview: CMIUtilFileStd interface. +// Overview: CMIUtilFileStd interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once // In-house headers: -#include "MIUtilString.h" +#include "MIUtilString.h" #include "MICmnBase.h" //++ ============================================================================ -// Details: MI common code utility class. File handling. -// Gotchas: None. -// Authors: Aidan Dodds 10/03/2014. -// Changes: None. +// Details: MI common code utility class. File handling. +// Gotchas: None. +// Authors: Aidan Dodds 10/03/2014. +// Changes: None. //-- class CMIUtilFileStd : public CMICmnBase { -// Static: -public: - static MIchar GetSlash( void ); + // Static: + public: + static MIchar GetSlash(void); -// Methods: -public: - /* ctor */ CMIUtilFileStd( void ); - // - bool CreateWrite( const CMIUtilString & vFileNamePath, bool & vwrbNewCreated ); - bool Write( const CMIUtilString & vData ); - bool Write( const MIchar * vpData, const MIuint vCharCnt ); - void Close( void ); - bool IsOk( void ) const; - bool IsFileExist( const CMIUtilString & vFileNamePath ) const; - const CMIUtilString & GetLineReturn( void ) const; - CMIUtilString StripOffFileName( const CMIUtilString & vDirectoryPath ) const; + // Methods: + public: + /* ctor */ CMIUtilFileStd(void); + // + bool CreateWrite(const CMIUtilString &vFileNamePath, bool &vwrbNewCreated); + bool Write(const CMIUtilString &vData); + bool Write(const MIchar *vpData, const MIuint vCharCnt); + void Close(void); + bool IsOk(void) const; + bool IsFileExist(const CMIUtilString &vFileNamePath) const; + const CMIUtilString &GetLineReturn(void) const; + CMIUtilString StripOffFileName(const CMIUtilString &vDirectoryPath) const; -// Overridden: -public: - // From CMICmnBase - /* dtor */ virtual ~CMIUtilFileStd( void ); - -// Attributes: -private: - CMIUtilString m_fileNamePath; - FILE * m_pFileHandle; - CMIUtilString m_constCharNewLine; - bool m_bFileError; // True = have a file error ATM, false = all ok -}; + // Overridden: + public: + // From CMICmnBase + /* dtor */ virtual ~CMIUtilFileStd(void); + // Attributes: + private: + CMIUtilString m_fileNamePath; + FILE *m_pFileHandle; + CMIUtilString m_constCharNewLine; + bool m_bFileError; // True = have a file error ATM, false = all ok +}; diff --git a/tools/lldb-mi/MIUtilMapIdToVariant.cpp b/tools/lldb-mi/MIUtilMapIdToVariant.cpp index 485ae2c0f0d2..413677268bed 100644 --- a/tools/lldb-mi/MIUtilMapIdToVariant.cpp +++ b/tools/lldb-mi/MIUtilMapIdToVariant.cpp @@ -8,117 +8,122 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilMapIdToVariant.cpp +// File: MIUtilMapIdToVariant.cpp // -// Overview: CMIUtilMapIdToVariant implementation. +// Overview: CMIUtilMapIdToVariant implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: #include "MIUtilMapIdToVariant.h" //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilMapIdToVariant constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilMapIdToVariant constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilMapIdToVariant::CMIUtilMapIdToVariant( void ) +CMIUtilMapIdToVariant::CMIUtilMapIdToVariant(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilMapIdToVariant destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilMapIdToVariant destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilMapIdToVariant::~CMIUtilMapIdToVariant( void ) +CMIUtilMapIdToVariant::~CMIUtilMapIdToVariant(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Remove at the data from *this container. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: Remove at the data from *this container. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMIUtilMapIdToVariant::Clear( void ) +void +CMIUtilMapIdToVariant::Clear(void) { - m_mapKeyToVariantValue.clear(); + m_mapKeyToVariantValue.clear(); } //++ ------------------------------------------------------------------------------------ -// Details: Check an ID is present already in *this container. -// Type: Method. -// Args: vId - (R) Unique ID i.e. GUID. -// Return: True - registered. -// False - not found. -// Throws: None. +// Details: Check an ID is present already in *this container. +// Type: Method. +// Args: vId - (R) Unique ID i.e. GUID. +// Return: True - registered. +// False - not found. +// Throws: None. //-- -bool CMIUtilMapIdToVariant::HaveAlready( const CMIUtilString & vId ) const +bool +CMIUtilMapIdToVariant::HaveAlready(const CMIUtilString &vId) const { - const MapKeyToVariantValue_t::const_iterator it = m_mapKeyToVariantValue.find( vId ); - if( it != m_mapKeyToVariantValue.end() ) - return true; - - return false; + const MapKeyToVariantValue_t::const_iterator it = m_mapKeyToVariantValue.find(vId); + if (it != m_mapKeyToVariantValue.end()) + return true; + + return false; } //++ ------------------------------------------------------------------------------------ -// Details: Determine if *this container is currently holding any data. -// Type: Method. -// Args: None. -// Return: bool - True - Yes empty, false - one or more data object present. -// Throws: None. +// Details: Determine if *this container is currently holding any data. +// Type: Method. +// Args: None. +// Return: bool - True - Yes empty, false - one or more data object present. +// Throws: None. //-- -bool CMIUtilMapIdToVariant::IsEmpty( void ) const +bool +CMIUtilMapIdToVariant::IsEmpty(void) const { - return m_mapKeyToVariantValue.empty(); + return m_mapKeyToVariantValue.empty(); } //++ ------------------------------------------------------------------------------------ -// Details: Check the ID is valid to be registered. -// Type: Method. -// Args: vId - (R) Unique ID i.e. GUID. -// Return: True - valid. -// False - not valid. -// Throws: None. +// Details: Check the ID is valid to be registered. +// Type: Method. +// Args: vId - (R) Unique ID i.e. GUID. +// Return: True - valid. +// False - not valid. +// Throws: None. //-- -bool CMIUtilMapIdToVariant::IsValid( const CMIUtilString & vId ) const +bool +CMIUtilMapIdToVariant::IsValid(const CMIUtilString &vId) const { - bool bValid = true; + bool bValid = true; + + if (vId.empty()) + bValid = false; - if( vId.empty() ) - bValid = false; - - return bValid; + return bValid; } //++ ------------------------------------------------------------------------------------ -// Details: Remove from *this contain a data object specified by ID. The data object -// when removed also calls its destructor should it have one. -// Type: Method. -// Args: vId - (R) Unique ID i.e. GUID. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Remove from *this contain a data object specified by ID. The data object +// when removed also calls its destructor should it have one. +// Type: Method. +// Args: vId - (R) Unique ID i.e. GUID. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilMapIdToVariant::Remove( const CMIUtilString & vId ) +bool +CMIUtilMapIdToVariant::Remove(const CMIUtilString &vId) { - const MapKeyToVariantValue_t::const_iterator it = m_mapKeyToVariantValue.find( vId ); - if( it != m_mapKeyToVariantValue.end() ) - { - m_mapKeyToVariantValue.erase( it ); - } + const MapKeyToVariantValue_t::const_iterator it = m_mapKeyToVariantValue.find(vId); + if (it != m_mapKeyToVariantValue.end()) + { + m_mapKeyToVariantValue.erase(it); + } - return MIstatus::success; + return MIstatus::success; } diff --git a/tools/lldb-mi/MIUtilMapIdToVariant.h b/tools/lldb-mi/MIUtilMapIdToVariant.h index 9570bfa0306f..6a7765d6022c 100644 --- a/tools/lldb-mi/MIUtilMapIdToVariant.h +++ b/tools/lldb-mi/MIUtilMapIdToVariant.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilMapIdToVariant.h +// File: MIUtilMapIdToVariant.h // -// Overview: CMIUtilMapIdToVariant interface. +// Overview: CMIUtilMapIdToVariant interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -27,122 +27,122 @@ // In-house headers: #include "MICmnBase.h" #include "MICmnResources.h" -#include "MIUtilString.h" +#include "MIUtilString.h" #include "MIUtilVariant.h" //++ ============================================================================ -// Details: MI common code utility class. Map type container that hold general -// object types (by being wrappin an variant wrapper) -// objects by ID. -// Gotchas: None. -// Authors: Illya Rudkin 19/06/2014. -// Changes: None. +// Details: MI common code utility class. Map type container that hold general +// object types (by being wrappin an variant wrapper) +// objects by ID. +// Gotchas: None. +// Authors: Illya Rudkin 19/06/2014. +// Changes: None. //-- class CMIUtilMapIdToVariant : public CMICmnBase { -// Methods: -public: - /* ctor */ CMIUtilMapIdToVariant( void ); - - template< typename T > - bool Add( const CMIUtilString & vId, const T & vData ); - void Clear( void ); - template< typename T > - bool Get( const CMIUtilString & vId, T & vrwData, bool & vrwbFound ) const; - bool HaveAlready( const CMIUtilString & vId ) const; - bool IsEmpty( void ) const; - bool Remove( const CMIUtilString & vId ); - -// Overridden: -public: - // From CMICmnBase - /* dtor */ virtual ~CMIUtilMapIdToVariant( void ); - -// Typdefs: -private: - typedef std::map< CMIUtilString, CMIUtilVariant > MapKeyToVariantValue_t; - typedef std::pair< CMIUtilString, CMIUtilVariant > MapPairKeyToVariantValue_t; - -// Methods: -private: - bool IsValid( const CMIUtilString & vId ) const; - -// Attributes: - MapKeyToVariantValue_t m_mapKeyToVariantValue; + // Methods: + public: + /* ctor */ CMIUtilMapIdToVariant(void); + + template bool Add(const CMIUtilString &vId, const T &vData); + void Clear(void); + template bool Get(const CMIUtilString &vId, T &vrwData, bool &vrwbFound) const; + bool HaveAlready(const CMIUtilString &vId) const; + bool IsEmpty(void) const; + bool Remove(const CMIUtilString &vId); + + // Overridden: + public: + // From CMICmnBase + /* dtor */ virtual ~CMIUtilMapIdToVariant(void); + + // Typdefs: + private: + typedef std::map MapKeyToVariantValue_t; + typedef std::pair MapPairKeyToVariantValue_t; + + // Methods: + private: + bool IsValid(const CMIUtilString &vId) const; + + // Attributes: + MapKeyToVariantValue_t m_mapKeyToVariantValue; }; //++ ------------------------------------------------------------------------------------ -// Details: Add to *this container a data object of general type identified by an ID. -// If the data with that ID already exists in the container it is replace with -// the new data specified. -// Type: Method. -// Args: T - The data object's variable type. -// vId - (R) Unique ID i.e. GUID. -// vData - (R) The general data object to be stored of some type. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Add to *this container a data object of general type identified by an ID. +// If the data with that ID already exists in the container it is replace with +// the new data specified. +// Type: Method. +// Args: T - The data object's variable type. +// vId - (R) Unique ID i.e. GUID. +// vData - (R) The general data object to be stored of some type. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -template< typename T > -bool CMIUtilMapIdToVariant::Add( const CMIUtilString & vId, const T & vData ) +template +bool +CMIUtilMapIdToVariant::Add(const CMIUtilString &vId, const T &vData) { - if( !IsValid( vId ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_VARIANT_ERR_MAP_KEY_INVALID ), vId.c_str() ) ); - return MIstatus::failure; - } - - const bool bOk = HaveAlready( vId ) ? Remove( vId ) : MIstatus::success; - if( bOk ) - { - CMIUtilVariant data; - data.Set< T >( vData ); - MapPairKeyToVariantValue_t pr( vId, data ); - m_mapKeyToVariantValue.insert( pr ); - } - - return bOk; + if (!IsValid(vId)) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_VARIANT_ERR_MAP_KEY_INVALID), vId.c_str())); + return MIstatus::failure; + } + + const bool bOk = HaveAlready(vId) ? Remove(vId) : MIstatus::success; + if (bOk) + { + CMIUtilVariant data; + data.Set(vData); + MapPairKeyToVariantValue_t pr(vId, data); + m_mapKeyToVariantValue.insert(pr); + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve a data object from *this container identified by the specified ID. -// Type: Method. -// Args: T - The data object's variable type. -// vId - (R) Unique ID i.e. GUID. -// vrwData - (W) Copy of the data object held. -// vrwbFound - (W) True = data found, false = data not found. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieve a data object from *this container identified by the specified ID. +// Type: Method. +// Args: T - The data object's variable type. +// vId - (R) Unique ID i.e. GUID. +// vrwData - (W) Copy of the data object held. +// vrwbFound - (W) True = data found, false = data not found. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -template< typename T > -bool CMIUtilMapIdToVariant::Get( const CMIUtilString & vId, T & vrwData, bool & vrwbFound ) const +template +bool +CMIUtilMapIdToVariant::Get(const CMIUtilString &vId, T &vrwData, bool &vrwbFound) const { - vrwbFound = false; - - if( !IsValid( vId ) ) - { - SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_VARIANT_ERR_MAP_KEY_INVALID ), vId.c_str() ) ); - return MIstatus::failure; - } - - const MapKeyToVariantValue_t::const_iterator it = m_mapKeyToVariantValue.find( vId ); - if( it != m_mapKeyToVariantValue.end() ) - { - const CMIUtilVariant & rData = (*it).second; - const T * pDataObj = rData.Get< T >(); - if( pDataObj != nullptr ) - { - vrwbFound = true; - vrwData = *pDataObj; - return MIstatus::success; - } - else - { - SetErrorDescription( MIRSRC( IDS_VARIANT_ERR_USED_BASECLASS ) ); - return MIstatus::failure; - } - } - - return MIstatus::success; + vrwbFound = false; + + if (!IsValid(vId)) + { + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_VARIANT_ERR_MAP_KEY_INVALID), vId.c_str())); + return MIstatus::failure; + } + + const MapKeyToVariantValue_t::const_iterator it = m_mapKeyToVariantValue.find(vId); + if (it != m_mapKeyToVariantValue.end()) + { + const CMIUtilVariant &rData = (*it).second; + const T *pDataObj = rData.Get(); + if (pDataObj != nullptr) + { + vrwbFound = true; + vrwData = *pDataObj; + return MIstatus::success; + } + else + { + SetErrorDescription(MIRSRC(IDS_VARIANT_ERR_USED_BASECLASS)); + return MIstatus::failure; + } + } + + return MIstatus::success; } diff --git a/tools/lldb-mi/MIUtilSingletonBase.h b/tools/lldb-mi/MIUtilSingletonBase.h index 23e971014882..44ad6cd9972c 100644 --- a/tools/lldb-mi/MIUtilSingletonBase.h +++ b/tools/lldb-mi/MIUtilSingletonBase.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilSingletonBase.h +// File: MIUtilSingletonBase.h // -// Overview: MI::ISingleton interface. +// Overview: MI::ISingleton interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -24,48 +24,47 @@ namespace MI { -// MI::ISingleton base class usage: +// MI::ISingleton base class usage: // -// class CMIDerivedClass -// : public MI::ISingleton< CMIDerivedClass > -// { -// friend MI::ISingleton< CMIDerivedClass >; +// class CMIDerivedClass +// : public MI::ISingleton< CMIDerivedClass > +// { +// friend MI::ISingleton< CMIDerivedClass >; // -// // Overridden: -// public: -// // From MI::ISingleton -// virtual bool Initialize( void ); -// virtual bool Shutdown( void ); -// }; +// // Overridden: +// public: +// // From MI::ISingleton +// virtual bool Initialize( void ); +// virtual bool Shutdown( void ); +// }; //++ ============================================================================ -// Details: Base class for the singleton pattern. -// Gotchas: Derived class must specify MI::ISingleton<> as a friend class. -// Authors: Aidan Dodds 17/03/2014. -// Changes: None. +// Details: Base class for the singleton pattern. +// Gotchas: Derived class must specify MI::ISingleton<> as a friend class. +// Authors: Aidan Dodds 17/03/2014. +// Changes: None. //-- -template< typename T > -class ISingleton +template class ISingleton { -// Statics: -public: - // Return an instance of the derived class - static T & Instance( void ) - { - // This will fail if the derived class has not - // declared itself to be a friend of MI::ISingleton - static T instance; + // Statics: + public: + // Return an instance of the derived class + static T & + Instance(void) + { + // This will fail if the derived class has not + // declared itself to be a friend of MI::ISingleton + static T instance; - return instance; - } + return instance; + } -// Overrideable: -public: - virtual bool Initialize( void ) = 0; - virtual bool Shutdown( void ) = 0; - // - /* dtor */ virtual ~ISingleton( void ) { }; + // Overrideable: + public: + virtual bool Initialize(void) = 0; + virtual bool Shutdown(void) = 0; + // + /* dtor */ virtual ~ISingleton(void){}; }; } // namespace MI - diff --git a/tools/lldb-mi/MIUtilSingletonHelper.h b/tools/lldb-mi/MIUtilSingletonHelper.h index ad36366830b7..a06a74296d03 100644 --- a/tools/lldb-mi/MIUtilSingletonHelper.h +++ b/tools/lldb-mi/MIUtilSingletonHelper.h @@ -8,18 +8,18 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilSingletonHelper.h +// File: MIUtilSingletonHelper.h // -// Overview: Contains template functions to aid the initialisation and -// shutdown of MI modules. MI modules (or components) can -// use other MI modules to help them achieve their one task -// (Modules only do one task). +// Overview: Contains template functions to aid the initialisation and +// shutdown of MI modules. MI modules (or components) can +// use other MI modules to help them achieve their one task +// (Modules only do one task). // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -32,64 +32,65 @@ namespace MI #include "MICmnResources.h" //++ ============================================================================ -// Details: Short cut helper function to simplify repeated initialisation of -// MI components (singletons) required by a client module. -// Type: Template method. -// Args: vErrorResrcId - (R) The string resource ID error message identifier to place in errMsg. -// vwrbOk - (RW) On input True = Try to initalise MI driver module. -// On output True = MI driver module initialise successfully. -// vwrErrMsg - (W) MI driver module initialise error description on failure. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Authors: Aidan Dodds 17/03/2014. -// Changes: None. +// Details: Short cut helper function to simplify repeated initialisation of +// MI components (singletons) required by a client module. +// Type: Template method. +// Args: vErrorResrcId - (R) The string resource ID error message identifier to place in errMsg. +// vwrbOk - (RW) On input True = Try to initalise MI driver module. +// On output True = MI driver module initialise successfully. +// vwrErrMsg - (W) MI driver module initialise error description on failure. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Authors: Aidan Dodds 17/03/2014. +// Changes: None. //-- -template< typename T > -bool ModuleInit( const MIint vErrorResrcId, bool & vwrbOk, CMIUtilString & vwrErrMsg ) +template +bool +ModuleInit(const MIint vErrorResrcId, bool &vwrbOk, CMIUtilString &vwrErrMsg) { - if( vwrbOk && !T::Instance().Initialize() ) - { - vwrbOk = MIstatus::failure; - vwrErrMsg = CMIUtilString::Format( MIRSRC( vErrorResrcId ), T::Instance().GetErrorDescription().c_str() ); - } + if (vwrbOk && !T::Instance().Initialize()) + { + vwrbOk = MIstatus::failure; + vwrErrMsg = CMIUtilString::Format(MIRSRC(vErrorResrcId), T::Instance().GetErrorDescription().c_str()); + } - return vwrbOk; + return vwrbOk; } //++ ============================================================================ -// Details: Short cut helper function to simplify repeated shutodown of -// MI components (singletons) required by a client module. -// Type: Template method. -// Args: vErrorResrcId - (R) The string resource ID error message identifier -// to place in errMsg. -// vwrbOk - (W) If not already false make false on module -// shutdown failure. -// vwrErrMsg - (RW) Append to existing error description string MI -// driver module initialise error description on -// failure. -// Return: True - Module shutdown succeeded. -// False - Module shutdown failed. -// Authors: Aidan Dodds 17/03/2014. -// Changes: None. +// Details: Short cut helper function to simplify repeated shutodown of +// MI components (singletons) required by a client module. +// Type: Template method. +// Args: vErrorResrcId - (R) The string resource ID error message identifier +// to place in errMsg. +// vwrbOk - (W) If not already false make false on module +// shutdown failure. +// vwrErrMsg - (RW) Append to existing error description string MI +// driver module initialise error description on +// failure. +// Return: True - Module shutdown succeeded. +// False - Module shutdown failed. +// Authors: Aidan Dodds 17/03/2014. +// Changes: None. //-- -template< typename T > -bool ModuleShutdown( const MIint vErrorResrcId, bool & vwrbOk, CMIUtilString & vwrErrMsg ) +template +bool +ModuleShutdown(const MIint vErrorResrcId, bool &vwrbOk, CMIUtilString &vwrErrMsg) { - bool bOk = MIstatus::success; + bool bOk = MIstatus::success; - if( !T::Instance().Shutdown() ) - { - const bool bMoreThanOneError( !vwrErrMsg.empty() ); - bOk = MIstatus::failure; - if( bMoreThanOneError ) - vwrErrMsg += ", "; - vwrErrMsg += CMIUtilString::Format( MIRSRC( vErrorResrcId ), T::Instance().GetErrorDescription().c_str() ); - } - - vwrbOk = bOk ? vwrbOk : MIstatus::failure; + if (!T::Instance().Shutdown()) + { + const bool bMoreThanOneError(!vwrErrMsg.empty()); + bOk = MIstatus::failure; + if (bMoreThanOneError) + vwrErrMsg += ", "; + vwrErrMsg += CMIUtilString::Format(MIRSRC(vErrorResrcId), T::Instance().GetErrorDescription().c_str()); + } - return bOk; + vwrbOk = bOk ? vwrbOk : MIstatus::failure; + + return bOk; } } // namespace MI - diff --git a/tools/lldb-mi/MIUtilString.cpp b/tools/lldb-mi/MIUtilString.cpp index 11c246290cab..0464eadccbff 100644 --- a/tools/lldb-mi/MIUtilString.cpp +++ b/tools/lldb-mi/MIUtilString.cpp @@ -8,673 +8,691 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilString.h +// File: MIUtilString.h // -// Overview: CMIUtilString implementation. +// Overview: CMIUtilString implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third party headers -#include // std::unique_ptr -#include // va_list, va_start, var_end -#include // std::stringstream -#include // for strcpy -#include // for ULONG_MAX +#include // std::unique_ptr +#include // va_list, va_start, var_end +#include // std::stringstream +#include // for strcpy +#include // for ULONG_MAX // In-house headers: #include "MIUtilString.h" //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilString constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilString constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilString::CMIUtilString( void ) -: std::string() +CMIUtilString::CMIUtilString(void) + : std::string() { } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilString constructor. -// Type: Method. -// Args: vpData - Pointer to UTF8 text data. -// Return: None. -// Throws: None. +// Details: CMIUtilString constructor. +// Type: Method. +// Args: vpData - Pointer to UTF8 text data. +// Return: None. +// Throws: None. //-- -CMIUtilString::CMIUtilString( const MIchar * vpData ) -: std::string( vpData ) +CMIUtilString::CMIUtilString(const MIchar *vpData) + : std::string(vpData) { } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilString constructor. -// Type: Method. -// Args: vpData - Pointer to UTF8 text data. -// Return: None. -// Throws: None. +// Details: CMIUtilString constructor. +// Type: Method. +// Args: vpData - Pointer to UTF8 text data. +// Return: None. +// Throws: None. //-- -CMIUtilString::CMIUtilString( const MIchar * const * vpData ) -: std::string( (const char *) vpData ) +CMIUtilString::CMIUtilString(const MIchar *const *vpData) + : std::string((const char *)vpData) { } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilString assigment operator. -// Type: Method. -// Args: vpRhs - Pointer to UTF8 text data. -// Return: CMIUtilString & - *this string. -// Throws: None. +// Details: CMIUtilString assigment operator. +// Type: Method. +// Args: vpRhs - Pointer to UTF8 text data. +// Return: CMIUtilString & - *this string. +// Throws: None. //-- -CMIUtilString & CMIUtilString::operator= ( const MIchar * vpRhs ) +CMIUtilString &CMIUtilString::operator=(const MIchar *vpRhs) { - if( *this == vpRhs ) - return *this; + if (*this == vpRhs) + return *this; - if( vpRhs != nullptr ) - { - assign( vpRhs ); - } + if (vpRhs != nullptr) + { + assign(vpRhs); + } - return *this; + return *this; } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilString assigment operator. -// Type: Method. -// Args: vrRhs - The other string to copy from. -// Return: CMIUtilString & - *this string. -// Throws: None. +// Details: CMIUtilString assigment operator. +// Type: Method. +// Args: vrRhs - The other string to copy from. +// Return: CMIUtilString & - *this string. +// Throws: None. //-- -CMIUtilString & CMIUtilString::operator= ( const std::string & vrRhs ) +CMIUtilString &CMIUtilString::operator=(const std::string &vrRhs) { - if( *this == vrRhs ) - return *this; + if (*this == vrRhs) + return *this; - assign( vrRhs ); - - return *this; + assign(vrRhs); + + return *this; } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilString destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilString destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilString::~CMIUtilString( void ) +CMIUtilString::~CMIUtilString(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Perform a snprintf format style on a string data. A new string object is -// created and returned. -// Type: Static method. -// Args: vrFormat - (R) Format string data instruction. -// vArgs - (R) Var list args of any type. -// Return: CMIUtilString - Number of splits found in the string data. -// Throws: None. +// Details: Perform a snprintf format style on a string data. A new string object is +// created and returned. +// Type: Static method. +// Args: vrFormat - (R) Format string data instruction. +// vArgs - (R) Var list args of any type. +// Return: CMIUtilString - Number of splits found in the string data. +// Throws: None. //-- -CMIUtilString CMIUtilString::FormatPriv( const CMIUtilString & vrFormat, va_list vArgs ) +CMIUtilString +CMIUtilString::FormatPriv(const CMIUtilString &vrFormat, va_list vArgs) { - CMIUtilString strResult; - MIint nFinal = 0; - MIint n = vrFormat.size(); - - // IOR: mysterious crash in this function on some windows builds not able to duplicate - // but found article which may be related. Crash occurs in vsnprintf() or va_copy() - // Duplicate vArgs va_list argument pointer to ensure that it can be safely used in - // a new frame - // http://julipedia.meroh.net/2011/09/using-vacopy-to-safely-pass-ap.html - va_list argsDup; - va_copy( argsDup, vArgs ); - - // Create a copy va_list to reset when we spin - va_list argsCpy; - va_copy( argsCpy, argsDup ); - - if( n == 0 ) - return strResult; - - n = n << 4; // Reserve 16 times as much the length of the vrFormat - - std::unique_ptr< char[] > pFormatted; - while( 1 ) - { - pFormatted.reset( new char[ n + 1 ] ); // +1 for safety margin - ::strncpy( &pFormatted[ 0 ], vrFormat.c_str(), n ); - - // We need to restore the variable argument list pointer to the start again - // before running vsnprintf() more then once - va_copy( argsDup, argsCpy ); - - nFinal = ::vsnprintf( &pFormatted[ 0 ], n, vrFormat.c_str(), argsDup ); - if( (nFinal < 0) || (nFinal >= n) ) - n += abs( nFinal - n + 1 ); - else - break; - } - - va_end( argsCpy ); - va_end( argsDup ); - - strResult = pFormatted.get(); - - return strResult; + CMIUtilString strResult; + MIint nFinal = 0; + MIint n = vrFormat.size(); + + // IOR: mysterious crash in this function on some windows builds not able to duplicate + // but found article which may be related. Crash occurs in vsnprintf() or va_copy() + // Duplicate vArgs va_list argument pointer to ensure that it can be safely used in + // a new frame + // http://julipedia.meroh.net/2011/09/using-vacopy-to-safely-pass-ap.html + va_list argsDup; + va_copy(argsDup, vArgs); + + // Create a copy va_list to reset when we spin + va_list argsCpy; + va_copy(argsCpy, argsDup); + + if (n == 0) + return strResult; + + n = n << 4; // Reserve 16 times as much the length of the vrFormat + + std::unique_ptr pFormatted; + while (1) + { + pFormatted.reset(new char[n + 1]); // +1 for safety margin + ::strncpy(&pFormatted[0], vrFormat.c_str(), n); + + // We need to restore the variable argument list pointer to the start again + // before running vsnprintf() more then once + va_copy(argsDup, argsCpy); + + nFinal = ::vsnprintf(&pFormatted[0], n, vrFormat.c_str(), argsDup); + if ((nFinal < 0) || (nFinal >= n)) + n += abs(nFinal - n + 1); + else + break; + } + + va_end(argsCpy); + va_end(argsDup); + + strResult = pFormatted.get(); + + return strResult; } //++ ------------------------------------------------------------------------------------ -// Details: Perform a snprintf format style on a string data. A new string object is -// created and returned. -// Type: Static method. -// Args: vrFormat - (R) Format string data instruction. -// ... - (R) Var list args of any type. -// Return: CMIUtilString - Number of splits found in the string data. -// Throws: None. +// Details: Perform a snprintf format style on a string data. A new string object is +// created and returned. +// Type: Static method. +// Args: vFormat - (R) Format string data instruction. +// ... - (R) Var list args of any type. +// Return: CMIUtilString - Number of splits found in the string data. +// Throws: None. //-- -CMIUtilString CMIUtilString::Format( const CMIUtilString & vrFormating, ... ) +CMIUtilString +CMIUtilString::Format(const CMIUtilString vFormating, ...) { - va_list args; - va_start( args, vrFormating ); - CMIUtilString strResult = CMIUtilString::FormatPriv( vrFormating, args ); - va_end( args ); + va_list args; + va_start(args, vFormating); + CMIUtilString strResult = CMIUtilString::FormatPriv(vFormating, args); + va_end(args); - return strResult; + return strResult; } //++ ------------------------------------------------------------------------------------ -// Details: Perform a snprintf format style on a string data. A new string object is -// created and returned. -// Type: Static method. -// Args: vrFormat - (R) Format string data instruction. -// vArgs - (R) Var list args of any type. -// Return: CMIUtilString - Number of splits found in the string data. -// Throws: None. +// Details: Perform a snprintf format style on a string data. A new string object is +// created and returned. +// Type: Static method. +// Args: vrFormat - (R) Format string data instruction. +// vArgs - (R) Var list args of any type. +// Return: CMIUtilString - Number of splits found in the string data. +// Throws: None. //-- -CMIUtilString CMIUtilString::FormatValist( const CMIUtilString & vrFormating, va_list vArgs ) +CMIUtilString +CMIUtilString::FormatValist(const CMIUtilString &vrFormating, va_list vArgs) { - return CMIUtilString::FormatPriv( vrFormating, vArgs ); + return CMIUtilString::FormatPriv(vrFormating, vArgs); } //++ ------------------------------------------------------------------------------------ -// Details: Splits string into array of strings using delimiter. If multiple delimiter -// are found in sequence then they are not added to the list of splits. -// Type: Method. -// Args: vData - (R) String data to be split up. -// vDelimiter - (R) Delimiter char or text. -// vwVecSplits - (W) Container of splits found in string data. -// Return: MIuint - Number of splits found in the string data. -// Throws: None. +// Details: Splits string into array of strings using delimiter. If multiple delimiter +// are found in sequence then they are not added to the list of splits. +// Type: Method. +// Args: vData - (R) String data to be split up. +// vDelimiter - (R) Delimiter char or text. +// vwVecSplits - (W) Container of splits found in string data. +// Return: MIuint - Number of splits found in the string data. +// Throws: None. //-- -MIuint CMIUtilString::Split( const CMIUtilString & vDelimiter, VecString_t & vwVecSplits ) const +MIuint +CMIUtilString::Split(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const { - vwVecSplits.clear(); - - if( this->empty() || vDelimiter.empty() ) - return 0; - - MIint nPos = find( vDelimiter ); - if( nPos == (MIint) std::string::npos ) - { - vwVecSplits.push_back( *this ); - return 1; - } - const MIint strLen( length() ); - if( nPos == strLen ) - { - vwVecSplits.push_back( *this ); - return 1; - } - - MIuint nAdd1( 1 ); - if( (nPos > 0) && (substr( 0, nPos ) != vDelimiter) ) - { - nPos = 0; - nAdd1 = 0; - } - MIint nPos2 = find( vDelimiter, nPos + 1 ); - while( nPos2 != (MIint) std::string::npos ) - { - const MIuint len( nPos2 - nPos - nAdd1 ); - const std::string strSection( substr( nPos + nAdd1, len ) ); - if( strSection != vDelimiter ) - vwVecSplits.push_back( strSection.c_str() ); - nPos += len + 1; - nPos2 = find( vDelimiter, nPos + 1 ); - nAdd1 = 0; - } - const std::string strSection( substr( nPos, strLen - nPos ) ); - if( (strSection.length() != 0) && (strSection != vDelimiter) ) - vwVecSplits.push_back( strSection.c_str() ); - - return vwVecSplits.size(); + vwVecSplits.clear(); + + if (this->empty() || vDelimiter.empty()) + return 0; + + MIint nPos = find(vDelimiter); + if (nPos == (MIint)std::string::npos) + { + vwVecSplits.push_back(*this); + return 1; + } + const MIint strLen(length()); + if (nPos == strLen) + { + vwVecSplits.push_back(*this); + return 1; + } + + MIuint nAdd1(1); + if ((nPos > 0) && (substr(0, nPos) != vDelimiter)) + { + nPos = 0; + nAdd1 = 0; + } + MIint nPos2 = find(vDelimiter, nPos + 1); + while (nPos2 != (MIint)std::string::npos) + { + const MIuint len(nPos2 - nPos - nAdd1); + const std::string strSection(substr(nPos + nAdd1, len)); + if (strSection != vDelimiter) + vwVecSplits.push_back(strSection.c_str()); + nPos += len + 1; + nPos2 = find(vDelimiter, nPos + 1); + nAdd1 = 0; + } + const std::string strSection(substr(nPos, strLen - nPos)); + if ((strSection.length() != 0) && (strSection != vDelimiter)) + vwVecSplits.push_back(strSection.c_str()); + + return vwVecSplits.size(); } //++ ------------------------------------------------------------------------------------ -// Details: Splits string into array of strings using delimiter. However the string is -// also considered for text surrounded by quotes. Text with quotes including the -// delimiter is treated as a whole. If multiple delimiter are found in sequence -// then they are not added to the list of splits. Quotes that are embedded in the -// the string as string formatted quotes are ignored (proceeded by a '\\') i.e. -// "\"MI GDB local C++.cpp\":88". -// Type: Method. -// Args: vData - (R) String data to be split up. -// vDelimiter - (R) Delimiter char or text. -// vwVecSplits - (W) Container of splits found in string data. -// Return: MIuint - Number of splits found in the string data. -// Throws: None. +// Details: Splits string into array of strings using delimiter. However the string is +// also considered for text surrounded by quotes. Text with quotes including the +// delimiter is treated as a whole. If multiple delimiter are found in sequence +// then they are not added to the list of splits. Quotes that are embedded in the +// the string as string formatted quotes are ignored (proceeded by a '\\') i.e. +// "\"MI GDB local C++.cpp\":88". +// Type: Method. +// Args: vData - (R) String data to be split up. +// vDelimiter - (R) Delimiter char or text. +// vwVecSplits - (W) Container of splits found in string data. +// Return: MIuint - Number of splits found in the string data. +// Throws: None. //-- -MIuint CMIUtilString::SplitConsiderQuotes( const CMIUtilString & vDelimiter, VecString_t & vwVecSplits ) const +MIuint +CMIUtilString::SplitConsiderQuotes(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const { - vwVecSplits.clear(); - - if( this->empty() || vDelimiter.empty() ) - return 0; - - MIint nPos = find( vDelimiter ); - if( nPos == (MIint) std::string::npos ) - { - vwVecSplits.push_back( *this ); - return 1; - } - const MIint strLen( length() ); - if( nPos == strLen ) - { - vwVecSplits.push_back( *this ); - return 1; - } - - // Look for more quotes - bool bHaveQuotes = false; - const MIchar cBckSlash = '\\'; - const MIchar cQuote = '"'; - MIint nPosQ = find( cQuote ); - MIint nPosQ2 = (MIint) std::string::npos; - if( nPosQ != (MIint) std::string::npos ) - { - nPosQ2 = nPosQ + 1; - while( nPosQ2 < strLen ) - { - nPosQ2 = find( cQuote, nPosQ2 ); - if( (nPosQ2 == (MIint) std::string::npos) || (at( nPosQ2 - 1 ) != cBckSlash) ) - break; - nPosQ2++; - } - bHaveQuotes = (nPosQ2 != (MIint) std::string::npos); - } - - MIuint nAdd1( 1 ); - if( (nPos > 0) && (substr( 0, nPos ) != vDelimiter) ) - { - nPos = 0; - nAdd1 = 0; - } - MIint nPos2 = find( vDelimiter, nPos + 1 ); - while( nPos2 != (MIint) std::string::npos ) - { - if( !bHaveQuotes || (bHaveQuotes && ((nPos2 > nPosQ2) || (nPos2 < nPosQ))) ) - { - // Extract text or quoted text - const MIuint len( nPos2 - nPos - nAdd1 ); - const std::string strSection( substr( nPos + nAdd1, len ) ); - if( strSection != vDelimiter ) - vwVecSplits.push_back( strSection.c_str() ); - nPos += len + 1; - nPos2 = find( vDelimiter, nPos + 1 ); - nAdd1 = 0; - - if( bHaveQuotes && (nPos2 > nPosQ2) ) - { - // Reset, look for more quotes - bHaveQuotes = false; - nPosQ = find( cQuote, nPos ); - nPosQ2 = (MIint) std::string::npos; - if( nPosQ != (MIint) std::string::npos ) - { - nPosQ2 = find( cQuote, nPosQ + 1 ); - bHaveQuotes = (nPosQ2 != (MIint) std::string::npos); - } - } - } - else - { - // Skip passed text in quotes - nPos2 = find( vDelimiter, nPosQ2 + 1 ); - } - } - const std::string strSection( substr( nPos, strLen - nPos ) ); - if( (strSection.length() != 0) && (strSection != vDelimiter) ) - vwVecSplits.push_back( strSection.c_str() ); - - return vwVecSplits.size(); + vwVecSplits.clear(); + + if (this->empty() || vDelimiter.empty()) + return 0; + + MIint nPos = find(vDelimiter); + if (nPos == (MIint)std::string::npos) + { + vwVecSplits.push_back(*this); + return 1; + } + const MIint strLen(length()); + if (nPos == strLen) + { + vwVecSplits.push_back(*this); + return 1; + } + + // Look for more quotes + bool bHaveQuotes = false; + const MIchar cBckSlash = '\\'; + const MIchar cQuote = '"'; + MIint nPosQ = find(cQuote); + MIint nPosQ2 = (MIint)std::string::npos; + if (nPosQ != (MIint)std::string::npos) + { + nPosQ2 = nPosQ + 1; + while (nPosQ2 < strLen) + { + nPosQ2 = find(cQuote, nPosQ2); + if ((nPosQ2 == (MIint)std::string::npos) || (at(nPosQ2 - 1) != cBckSlash)) + break; + nPosQ2++; + } + bHaveQuotes = (nPosQ2 != (MIint)std::string::npos); + } + + MIuint nAdd1(1); + if ((nPos > 0) && (substr(0, nPos) != vDelimiter)) + { + nPos = 0; + nAdd1 = 0; + } + MIint nPos2 = find(vDelimiter, nPos + 1); + while (nPos2 != (MIint)std::string::npos) + { + if (!bHaveQuotes || (bHaveQuotes && ((nPos2 > nPosQ2) || (nPos2 < nPosQ)))) + { + // Extract text or quoted text + const MIuint len(nPos2 - nPos - nAdd1); + const std::string strSection(substr(nPos + nAdd1, len)); + if (strSection != vDelimiter) + vwVecSplits.push_back(strSection.c_str()); + nPos += len + 1; + nPos2 = find(vDelimiter, nPos + 1); + nAdd1 = 0; + + if (bHaveQuotes && (nPos2 > nPosQ2)) + { + // Reset, look for more quotes + bHaveQuotes = false; + nPosQ = find(cQuote, nPos); + nPosQ2 = (MIint)std::string::npos; + if (nPosQ != (MIint)std::string::npos) + { + nPosQ2 = find(cQuote, nPosQ + 1); + bHaveQuotes = (nPosQ2 != (MIint)std::string::npos); + } + } + } + else + { + // Skip passed text in quotes + nPos2 = find(vDelimiter, nPosQ2 + 1); + } + } + const std::string strSection(substr(nPos, strLen - nPos)); + if ((strSection.length() != 0) && (strSection != vDelimiter)) + vwVecSplits.push_back(strSection.c_str()); + + return vwVecSplits.size(); } //++ ------------------------------------------------------------------------------------ -// Details: Remove '\n' from the end of string if found. It does not alter -// *this string. -// Type: Method. -// Args: None. -// Return: CMIUtilString - New version of the string. -// Throws: None. +// Details: Remove '\n' from the end of string if found. It does not alter +// *this string. +// Type: Method. +// Args: None. +// Return: CMIUtilString - New version of the string. +// Throws: None. //-- -CMIUtilString CMIUtilString::StripCREndOfLine( void ) const +CMIUtilString +CMIUtilString::StripCREndOfLine(void) const { - const MIint nPos = rfind( '\n' ); - if( nPos == (MIint) std::string::npos ) - return *this; + const MIint nPos = rfind('\n'); + if (nPos == (MIint)std::string::npos) + return *this; + + const CMIUtilString strNew(substr(0, nPos).c_str()); - const CMIUtilString strNew( substr( 0, nPos ).c_str() ); - - return strNew; + return strNew; } //++ ------------------------------------------------------------------------------------ -// Details: Remove all '\n' from the string and replace with a space. It does not alter -// *this string. -// Type: Method. -// Args: None. -// Return: CMIUtilString - New version of the string. -// Throws: None. +// Details: Remove all '\n' from the string and replace with a space. It does not alter +// *this string. +// Type: Method. +// Args: None. +// Return: CMIUtilString - New version of the string. +// Throws: None. //-- -CMIUtilString CMIUtilString::StripCRAll( void ) const +CMIUtilString +CMIUtilString::StripCRAll(void) const { - return FindAndReplace( "\n", " " ); + return FindAndReplace("\n", " "); } //++ ------------------------------------------------------------------------------------ -// Details: Find and replace all matches of a sub string with another string. It does not -// alter *this string. -// Type: Method. -// Args: vFind - (R) The string to look for. -// vReplaceWith - (R) The string to replace the vFind match. -// Return: CMIUtilString - New version of the string. -// Throws: None. +// Details: Find and replace all matches of a sub string with another string. It does not +// alter *this string. +// Type: Method. +// Args: vFind - (R) The string to look for. +// vReplaceWith - (R) The string to replace the vFind match. +// Return: CMIUtilString - New version of the string. +// Throws: None. //-- -CMIUtilString CMIUtilString::FindAndReplace( const CMIUtilString & vFind, const CMIUtilString & vReplaceWith ) const +CMIUtilString +CMIUtilString::FindAndReplace(const CMIUtilString &vFind, const CMIUtilString &vReplaceWith) const { - if( vFind.empty() || this->empty() ) - return *this; - - MIint nPos = find( vFind ); - if( nPos == (MIint) std::string::npos ) - return *this; - - CMIUtilString strNew( *this ); - while( nPos != (MIint) std::string::npos ) - { - strNew.replace( nPos, vFind.length(), vReplaceWith ); - nPos += vReplaceWith.length(); - nPos = strNew.find( vFind, nPos ); - } - - return strNew; + if (vFind.empty() || this->empty()) + return *this; + + MIint nPos = find(vFind); + if (nPos == (MIint)std::string::npos) + return *this; + + CMIUtilString strNew(*this); + while (nPos != (MIint)std::string::npos) + { + strNew.replace(nPos, vFind.length(), vReplaceWith); + nPos += vReplaceWith.length(); + nPos = strNew.find(vFind, nPos); + } + + return strNew; } //++ ------------------------------------------------------------------------------------ -// Details: Check if *this string is a decimal number. -// Type: Method. -// Args: None. -// Return: bool - True = yes number, false not a number. -// Throws: None. +// Details: Check if *this string is a decimal number. +// Type: Method. +// Args: None. +// Return: bool - True = yes number, false not a number. +// Throws: None. //-- -bool CMIUtilString::IsNumber( void ) const +bool +CMIUtilString::IsNumber(void) const { - if( empty() ) - return false; + if (empty()) + return false; - if( (at( 0 ) == '-') && (length() == 1) ) - return false; + if ((at(0) == '-') && (length() == 1)) + return false; - const MIint nPos = find_first_not_of( "-.0123456789" ); - if( nPos != (MIint) std::string::npos ) - return false; + const MIint nPos = find_first_not_of("-.0123456789"); + if (nPos != (MIint)std::string::npos) + return false; - return true; + return true; } //++ ------------------------------------------------------------------------------------ -// Details: Extract the number from the string. The number can be either a hexadecimal or -// natural number. It cannot contain other non-numeric characters. -// Type: Method. -// Args: vwrNumber - (W) Number exracted from the string. -// Return: bool - True = yes number, false not a number. -// Throws: None. +// Details: Extract the number from the string. The number can be either a hexadecimal or +// natural number. It cannot contain other non-numeric characters. +// Type: Method. +// Args: vwrNumber - (W) Number exracted from the string. +// Return: bool - True = yes number, false not a number. +// Throws: None. //-- -bool CMIUtilString::ExtractNumber( MIint64 & vwrNumber ) const +bool +CMIUtilString::ExtractNumber(MIint64 &vwrNumber) const { - vwrNumber = 0; - - if( !IsNumber() ) - { - if( ExtractNumberFromHexadecimal( vwrNumber ) ) - return true; + vwrNumber = 0; + + if (!IsNumber()) + { + if (ExtractNumberFromHexadecimal(vwrNumber)) + return true; - return false; - } + return false; + } - std::stringstream ss( const_cast< CMIUtilString & >( *this ) ); - ss >> vwrNumber; + std::stringstream ss(const_cast(*this)); + ss >> vwrNumber; - return true; + return true; } //++ ------------------------------------------------------------------------------------ -// Details: Extract the number from the hexadecimal string.. -// Type: Method. -// Args: vwrNumber - (W) Number exracted from the string. -// Return: bool - True = yes number, false not a number. -// Throws: None. +// Details: Extract the number from the hexadecimal string.. +// Type: Method. +// Args: vwrNumber - (W) Number exracted from the string. +// Return: bool - True = yes number, false not a number. +// Throws: None. //-- -bool CMIUtilString::ExtractNumberFromHexadecimal( MIint64 & vwrNumber ) const +bool +CMIUtilString::ExtractNumberFromHexadecimal(MIint64 &vwrNumber) const { - vwrNumber = 0; - - const MIint nPos = find_first_not_of( "x01234567890ABCDEFabcedf" ); - if( nPos != (MIint) std::string::npos ) - return false; - - const MIint64 nNum = ::strtoul( this->c_str(), nullptr, 16 ); - if( nNum != ULONG_MAX ) - { - vwrNumber = nNum; - return true; - } - - return true; + vwrNumber = 0; + + const MIint nPos = find_first_not_of("x01234567890ABCDEFabcedf"); + if (nPos != (MIint)std::string::npos) + return false; + + const MIint64 nNum = ::strtoul(this->c_str(), nullptr, 16); + if (nNum != LONG_MAX) + { + vwrNumber = nNum; + return true; + } + + return true; } //++ ------------------------------------------------------------------------------------ -// Details: Determine if the text is all valid alpha numeric characters. Letters can be -// either upper or lower case. -// Type: Static method. -// Args: vrText - (R) The text data to examine. -// Return: bool - True = yes all alpha, false = one or more chars is non alpha. -// Throws: None. +// Details: Determine if the text is all valid alpha numeric characters. Letters can be +// either upper or lower case. +// Type: Static method. +// Args: vrText - (R) The text data to examine. +// Return: bool - True = yes all alpha, false = one or more chars is non alpha. +// Throws: None. //-- -bool CMIUtilString::IsAllValidAlphaAndNumeric( const MIchar & vrText ) +bool +CMIUtilString::IsAllValidAlphaAndNumeric(const MIchar &vrText) { - const MIuint len = ::strlen( &vrText ); - if( len == 0 ) - return false; - - MIchar * pPtr = const_cast< MIchar * >( &vrText ); - for( MIuint i = 0; i < len; i++, pPtr++ ) - { - const MIchar c = *pPtr; - if( ::isalnum( (int) c ) == 0 ) - return false; - } - - return true; + const MIuint len = ::strlen(&vrText); + if (len == 0) + return false; + + MIchar *pPtr = const_cast(&vrText); + for (MIuint i = 0; i < len; i++, pPtr++) + { + const MIchar c = *pPtr; + if (::isalnum((int)c) == 0) + return false; + } + + return true; } //++ ------------------------------------------------------------------------------------ // Details: Check if two strings share equal contents. -// Type: Method. -// Args: vrLhs - (R) String A. -// vrRhs - (R) String B. -// Return: bool - True = yes equal, false - different. -// Throws: None. +// Type: Method. +// Args: vrLhs - (R) String A. +// vrRhs - (R) String B. +// Return: bool - True = yes equal, false - different. +// Throws: None. //-- -bool CMIUtilString::Compare( const CMIUtilString & vrLhs, const CMIUtilString & vrRhs ) +bool +CMIUtilString::Compare(const CMIUtilString &vrLhs, const CMIUtilString &vrRhs) { - // Check the sizes match - if( vrLhs.size() != vrRhs.size() ) - return false; + // Check the sizes match + if (vrLhs.size() != vrRhs.size()) + return false; - return (::strncmp( vrLhs.c_str(), vrRhs.c_str(), vrLhs.size() ) == 0); + return (::strncmp(vrLhs.c_str(), vrRhs.c_str(), vrLhs.size()) == 0); } //++ ------------------------------------------------------------------------------------ // Details: Remove from either end of *this string the following: " \t\n\v\f\r". -// Type: Method. -// Args: None. -// Return: CMIUtilString - Trimmed string. -// Throws: None. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Trimmed string. +// Throws: None. //-- -CMIUtilString CMIUtilString::Trim( void ) const +CMIUtilString +CMIUtilString::Trim(void) const { - CMIUtilString strNew( *this ); - const MIchar * pWhiteSpace = " \t\n\v\f\r"; - const MIint nPos = find_last_not_of( pWhiteSpace ); - if( nPos != (MIint) std::string::npos ) - { - strNew = substr( 0, nPos + 1 ).c_str(); - } - const MIint nPos2 = strNew.find_first_not_of( pWhiteSpace ); - if( nPos2 != (MIint) std::string::npos ) - { - strNew = strNew.substr( nPos2 ).c_str(); - } - - return strNew; + CMIUtilString strNew(*this); + const MIchar *pWhiteSpace = " \t\n\v\f\r"; + const MIint nPos = find_last_not_of(pWhiteSpace); + if (nPos != (MIint)std::string::npos) + { + strNew = substr(0, nPos + 1).c_str(); + } + const MIint nPos2 = strNew.find_first_not_of(pWhiteSpace); + if (nPos2 != (MIint)std::string::npos) + { + strNew = strNew.substr(nPos2).c_str(); + } + + return strNew; } - + //++ ------------------------------------------------------------------------------------ // Details: Remove from either end of *this string the specified character. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Trimmed string. -// Throws: None. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Trimmed string. +// Throws: None. //-- -CMIUtilString CMIUtilString::Trim( const MIchar vChar ) const +CMIUtilString +CMIUtilString::Trim(const MIchar vChar) const { - CMIUtilString strNew( *this ); - const MIint nLen = strNew.length(); - if( nLen > 1 ) - { - if( (strNew[ 0 ] == vChar) && (strNew[ nLen - 1 ] == vChar) ) - strNew = strNew.substr( 1, nLen - 2 ).c_str(); - } - - return strNew; + CMIUtilString strNew(*this); + const MIint nLen = strNew.length(); + if (nLen > 1) + { + if ((strNew[0] == vChar) && (strNew[nLen - 1] == vChar)) + strNew = strNew.substr(1, nLen - 2).c_str(); + } + + return strNew; } - + //++ ------------------------------------------------------------------------------------ // Details: Do a printf equivalent for printing a number in binary i.e. "b%llB". -// Type: Static method. -// Args: vnDecimal - (R) The number to represent in binary. -// Return: CMIUtilString - Binary number in text. -// Throws: None. +// Type: Static method. +// Args: vnDecimal - (R) The number to represent in binary. +// Return: CMIUtilString - Binary number in text. +// Throws: None. //-- -CMIUtilString CMIUtilString::FormatBinary( const MIuint64 vnDecimal ) +CMIUtilString +CMIUtilString::FormatBinary(const MIuint64 vnDecimal) { - CMIUtilString strBinaryNumber; - - const MIuint nConstBits = 64; - MIuint nRem[ nConstBits + 1 ]; - MIint i = 0; - MIuint nLen = 0; - MIuint64 nNum = vnDecimal; - while( (nNum > 0) && (nLen < nConstBits) ) - { - nRem[ i++ ] = nNum % 2; - nNum = nNum >> 1; - nLen++; - } - MIchar pN[ nConstBits + 1 ]; - MIuint j = 0; - for( i = nLen; i > 0; --i, j++ ) - { - pN[ j ] = '0' + nRem[ i - 1 ]; - } - pN[ j ] = 0; // String NUL termination - - strBinaryNumber = CMIUtilString::Format( "0b%s", &pN[ 0 ] ); - - return strBinaryNumber; + CMIUtilString strBinaryNumber; + + const MIuint nConstBits = 64; + MIuint nRem[nConstBits + 1]; + MIint i = 0; + MIuint nLen = 0; + MIuint64 nNum = vnDecimal; + while ((nNum > 0) && (nLen < nConstBits)) + { + nRem[i++] = nNum % 2; + nNum = nNum >> 1; + nLen++; + } + MIchar pN[nConstBits + 1]; + MIuint j = 0; + for (i = nLen; i > 0; --i, j++) + { + pN[j] = '0' + nRem[i - 1]; + } + pN[j] = 0; // String NUL termination + + strBinaryNumber = CMIUtilString::Format("0b%s", &pN[0]); + + return strBinaryNumber; } - + //++ ------------------------------------------------------------------------------------ -// Details: Remove from a string doubled up characters so only one set left. Characters -// are only removed if the previous character is already a same character. -// Type: Method. -// Args: vChar - (R) The character to search for and remove adjacent duplicates. -// Return: CMIUtilString - New version of the string. -// Throws: None. +// Details: Remove from a string doubled up characters so only one set left. Characters +// are only removed if the previous character is already a same character. +// Type: Method. +// Args: vChar - (R) The character to search for and remove adjacent duplicates. +// Return: CMIUtilString - New version of the string. +// Throws: None. //-- -CMIUtilString CMIUtilString::RemoveRepeatedCharacters( const MIchar vChar ) +CMIUtilString +CMIUtilString::RemoveRepeatedCharacters(const MIchar vChar) { - return RemoveRepeatedCharacters( 0, vChar ); + return RemoveRepeatedCharacters(0, vChar); } - + //++ ------------------------------------------------------------------------------------ -// Details: Recursively remove from a string doubled up characters so only one set left. -// Characters are only removed if the previous character is already a same -// character. -// Type: Method. -// Args: vChar - (R) The character to search for and remove adjacent duplicates. -// vnPos - (R) Character position in the string. -// Return: CMIUtilString - New version of the string. -// Throws: None. +// Details: Recursively remove from a string doubled up characters so only one set left. +// Characters are only removed if the previous character is already a same +// character. +// Type: Method. +// Args: vChar - (R) The character to search for and remove adjacent duplicates. +// vnPos - (R) Character position in the string. +// Return: CMIUtilString - New version of the string. +// Throws: None. //-- -CMIUtilString CMIUtilString::RemoveRepeatedCharacters( const MIint vnPos, const MIchar vChar ) +CMIUtilString +CMIUtilString::RemoveRepeatedCharacters(const MIint vnPos, const MIchar vChar) { - const MIchar cQuote = '"'; + const MIchar cQuote = '"'; - // Look for first quote of two - MIint nPos = find( cQuote, vnPos ); - if( nPos == (MIint) std::string::npos ) - return *this; + // Look for first quote of two + MIint nPos = find(cQuote, vnPos); + if (nPos == (MIint)std::string::npos) + return *this; - const MIint nPosNext = nPos + 1; - if( nPosNext > (MIint) length() ) - return *this; + const MIint nPosNext = nPos + 1; + if (nPosNext > (MIint)length()) + return *this; - if( at( nPosNext ) == cQuote ) - { - *this = substr( 0, nPos ) + substr( nPosNext, length() ); - RemoveRepeatedCharacters( nPosNext, vChar ); - } + if (at(nPosNext) == cQuote) + { + *this = substr(0, nPos) + substr(nPosNext, length()); + RemoveRepeatedCharacters(nPosNext, vChar); + } - return *this; + return *this; } //++ ------------------------------------------------------------------------------------ -// Details: Is the text in *this string surrounded by quotes. -// Type: Method. -// Args: None. -// Return: bool - True = Yes string is quoted, false = no quoted. -// Throws: None. +// Details: Is the text in *this string surrounded by quotes. +// Type: Method. +// Args: None. +// Return: bool - True = Yes string is quoted, false = no quoted. +// Throws: None. //-- -bool CMIUtilString::IsQuoted( void ) const +bool +CMIUtilString::IsQuoted(void) const { - const MIchar cQuote = '"'; - - if( at( 0 ) != cQuote ) - return false; + const MIchar cQuote = '"'; + + if (at(0) != cQuote) + return false; - const MIint nLen = length(); - if( (nLen > 0) && (at( nLen - 1 ) != cQuote) ) - return false; + const MIint nLen = length(); + if ((nLen > 0) && (at(nLen - 1) != cQuote)) + return false; - return true; + return true; } - \ No newline at end of file diff --git a/tools/lldb-mi/MIUtilString.h b/tools/lldb-mi/MIUtilString.h index 30b027a9d314..162dcbf68852 100644 --- a/tools/lldb-mi/MIUtilString.h +++ b/tools/lldb-mi/MIUtilString.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilString.h +// File: MIUtilString.h // -// Overview: CMIUtilString interface. +// Overview: CMIUtilString interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -26,60 +26,60 @@ #include // In-house headers: -#include "MIDataTypes.h" +#include "MIDataTypes.h" //++ ============================================================================ -// Details: MI common code utility class. Used to help handle text. -// Derived from std::string -// Gotchas: None. -// Authors: Illya Rudkin 02/02/2014. -// Changes: None. +// Details: MI common code utility class. Used to help handle text. +// Derived from std::string +// Gotchas: None. +// Authors: Illya Rudkin 02/02/2014. +// Changes: None. //-- class CMIUtilString : public std::string { -// Typdefs: -public: - typedef std::vector< CMIUtilString > VecString_t; + // Typdefs: + public: + typedef std::vector VecString_t; -// Static method: -public: - static CMIUtilString Format( const CMIUtilString & vrFormating, ... ); - static CMIUtilString FormatBinary( const MIuint64 vnDecimal ); - static CMIUtilString FormatValist( const CMIUtilString & vrFormating, va_list vArgs ); - static bool IsAllValidAlphaAndNumeric( const MIchar & vrText ); - static bool Compare( const CMIUtilString & vrLhs, const CMIUtilString & vrRhs ); + // Static method: + public: + static CMIUtilString Format(const CMIUtilString vFormating, ...); + static CMIUtilString FormatBinary(const MIuint64 vnDecimal); + static CMIUtilString FormatValist(const CMIUtilString &vrFormating, va_list vArgs); + static bool IsAllValidAlphaAndNumeric(const MIchar &vrText); + static bool Compare(const CMIUtilString &vrLhs, const CMIUtilString &vrRhs); -// Methods: -public: - /* ctor */ CMIUtilString( void ); - /* ctor */ CMIUtilString( const MIchar * vpData ); - /* ctor */ CMIUtilString( const MIchar * const * vpData ); - // - bool ExtractNumber( MIint64 & vwrNumber ) const; - CMIUtilString FindAndReplace( const CMIUtilString & vFind, const CMIUtilString & vReplaceWith ) const; - bool IsNumber( void ) const; - bool IsQuoted( void ) const; - CMIUtilString RemoveRepeatedCharacters( const MIchar vChar ); - MIuint Split( const CMIUtilString & vDelimiter, VecString_t & vwVecSplits ) const; - MIuint SplitConsiderQuotes( const CMIUtilString & vDelimiter, VecString_t & vwVecSplits ) const; - CMIUtilString StripCREndOfLine( void ) const; - CMIUtilString StripCRAll( void ) const; - CMIUtilString Trim( void ) const; - CMIUtilString Trim( const MIchar vChar ) const; - // - CMIUtilString & operator= ( const MIchar * vpRhs ); - CMIUtilString & operator= ( const std::string & vrRhs ); - -// Overrideable: -public: - /* dtor */ virtual ~CMIUtilString( void ); - -// Static method: -private: - static CMIUtilString FormatPriv( const CMIUtilString & vrFormat, va_list vArgs ); + // Methods: + public: + /* ctor */ CMIUtilString(void); + /* ctor */ CMIUtilString(const MIchar *vpData); + /* ctor */ CMIUtilString(const MIchar *const *vpData); + // + bool ExtractNumber(MIint64 &vwrNumber) const; + CMIUtilString FindAndReplace(const CMIUtilString &vFind, const CMIUtilString &vReplaceWith) const; + bool IsNumber(void) const; + bool IsQuoted(void) const; + CMIUtilString RemoveRepeatedCharacters(const MIchar vChar); + MIuint Split(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const; + MIuint SplitConsiderQuotes(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const; + CMIUtilString StripCREndOfLine(void) const; + CMIUtilString StripCRAll(void) const; + CMIUtilString Trim(void) const; + CMIUtilString Trim(const MIchar vChar) const; + // + CMIUtilString &operator=(const MIchar *vpRhs); + CMIUtilString &operator=(const std::string &vrRhs); -// Methods: -private: - bool ExtractNumberFromHexadecimal( MIint64 & vwrNumber ) const; - CMIUtilString RemoveRepeatedCharacters( const MIint vnPos, const MIchar vChar ); + // Overrideable: + public: + /* dtor */ virtual ~CMIUtilString(void); + + // Static method: + private: + static CMIUtilString FormatPriv(const CMIUtilString &vrFormat, va_list vArgs); + + // Methods: + private: + bool ExtractNumberFromHexadecimal(MIint64 &vwrNumber) const; + CMIUtilString RemoveRepeatedCharacters(const MIint vnPos, const MIchar vChar); }; diff --git a/tools/lldb-mi/MIUtilSystemLinux.cpp b/tools/lldb-mi/MIUtilSystemLinux.cpp index b1755a32a67e..8227302356c5 100644 --- a/tools/lldb-mi/MIUtilSystemLinux.cpp +++ b/tools/lldb-mi/MIUtilSystemLinux.cpp @@ -8,112 +8,116 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilSystemLinux.cpp +// File: MIUtilSystemLinux.cpp // -// Overview: CMIUtilSystemLinux implementation. +// Overview: CMIUtilSystemLinux implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- -#if defined( __FreeBSD__ ) || defined( __linux__ ) +#if defined(__FreeBSD__) || defined(__linux__) // In-house headers: #include "MIUtilSystemLinux.h" #include "MICmnResources.h" //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilSystemLinux constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilSystemLinux constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilSystemLinux::CMIUtilSystemLinux( void ) +CMIUtilSystemLinux::CMIUtilSystemLinux(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilSystemLinux destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilSystemLinux destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilSystemLinux::~CMIUtilSystemLinux( void ) +CMIUtilSystemLinux::~CMIUtilSystemLinux(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the OS system error message for the given system error code. -// Type: Method. -// Args: vError - (R) OS error code value. -// vrwErrorMsg - (W) The error message. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieve the OS system error message for the given system error code. +// Type: Method. +// Args: vError - (R) OS error code value. +// vrwErrorMsg - (W) The error message. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilSystemLinux::GetOSErrorMsg( const MIint vError, CMIUtilString & vrwErrorMsg ) const +bool +CMIUtilSystemLinux::GetOSErrorMsg(const MIint vError, CMIUtilString &vrwErrorMsg) const { - // Reset - vrwErrorMsg.clear(); + // Reset + vrwErrorMsg.clear(); - bool bOk = MIstatus::failure; - - // ToDo: Implement LINUX version - - return bOk; + bool bOk = MIstatus::failure; + + // ToDo: Implement LINUX version + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve if possible the OS last error description. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Error description. -// Throws: None. +// Details: Retrieve if possible the OS last error description. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Error description. +// Throws: None. //-- -CMIUtilString CMIUtilSystemLinux::GetOSLastError( void ) const +CMIUtilString +CMIUtilSystemLinux::GetOSLastError(void) const { - CMIUtilString errorMsg( "Error fn not implemented " ); - - // ToDo: Implement LINUX version - - return errorMsg; + CMIUtilString errorMsg("Error fn not implemented "); + + // ToDo: Implement LINUX version + + return errorMsg; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieves the fully qualified path for the this application. If the function -// fails the string is filled with the error message. -// Type: Method. -// Args: vrwFileNamePath - (W) The excutable's name and path or last error description. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieves the fully qualified path for the this application. If the function +// fails the string is filled with the error message. +// Type: Method. +// Args: vrwFileNamePath - (W) The excutable's name and path or last error description. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilSystemLinux::GetExecutablesPath( CMIUtilString & vrwFileNamePath ) const +bool +CMIUtilSystemLinux::GetExecutablesPath(CMIUtilString &vrwFileNamePath) const { - vrwFileNamePath = CMIUtilString( "." ); - return MIstatus::success; + vrwFileNamePath = CMIUtilString("."); + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieves the fully qualified path for the Log file for this application. -// If the function fails the string is filled with the error message. -// Append a dummy file name on the end of the path. This will be stripped off -// later and the real log file name replaces it. -// Type: Method. -// Args: vrwFileNamePath - (W) The Log file's name and path or last error description. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieves the fully qualified path for the Log file for this application. +// If the function fails the string is filled with the error message. +// Append a dummy file name on the end of the path. This will be stripped off +// later and the real log file name replaces it. +// Type: Method. +// Args: vrwFileNamePath - (W) The Log file's name and path or last error description. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilSystemLinux::GetLogFilesPath( CMIUtilString & vrwFileNamePath ) const +bool +CMIUtilSystemLinux::GetLogFilesPath(CMIUtilString &vrwFileNamePath) const { - vrwFileNamePath = CMIUtilString( "." ); - return MIstatus::success; + vrwFileNamePath = CMIUtilString("."); + return MIstatus::success; } #endif // #if defined( __linux__ ) diff --git a/tools/lldb-mi/MIUtilSystemLinux.h b/tools/lldb-mi/MIUtilSystemLinux.h index 1fd2c525992a..451b887e209a 100644 --- a/tools/lldb-mi/MIUtilSystemLinux.h +++ b/tools/lldb-mi/MIUtilSystemLinux.h @@ -8,48 +8,48 @@ //===----------------------------------------------------------------------===// //++ -// File: CMIUtilSystemLinux.h +// File: CMIUtilSystemLinux.h // -// Overview: CMIUtilSystemLinux interface. +// Overview: CMIUtilSystemLinux interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once -#if defined( __FreeBSD__ ) || defined( __linux__ ) +#if defined(__FreeBSD__) || defined(__linux__) // In-house headers: -#include "MIUtilString.h" +#include "MIUtilString.h" //++ ============================================================================ -// Details: MI common code utility class. Used to set or retrieve information -// about the current system or user. -// *** If you change, remove or add functionality it must be replicated -// *** for the all platforms supported; Windows, OSX, LINUX -// Gotchas: None. -// Authors: Illya Rudkin 29/01/2014. -// Changes: None. +// Details: MI common code utility class. Used to set or retrieve information +// about the current system or user. +// *** If you change, remove or add functionality it must be replicated +// *** for the all platforms supported; Windows, OSX, LINUX +// Gotchas: None. +// Authors: Illya Rudkin 29/01/2014. +// Changes: None. //-- class CMIUtilSystemLinux { -// Methods: -public: - /* ctor */ CMIUtilSystemLinux( void ); - - bool GetOSErrorMsg( const MIint vError, CMIUtilString & vrwErrorMsg ) const; - CMIUtilString GetOSLastError( void ) const; - bool GetExecutablesPath( CMIUtilString & vrwFileNamePath ) const; - bool GetLogFilesPath( CMIUtilString & vrwFileNamePath ) const; - -// Overrideable: -public: - // From CMICmnBase - /* dtor */ virtual ~CMIUtilSystemLinux( void ); + // Methods: + public: + /* ctor */ CMIUtilSystemLinux(void); + + bool GetOSErrorMsg(const MIint vError, CMIUtilString &vrwErrorMsg) const; + CMIUtilString GetOSLastError(void) const; + bool GetExecutablesPath(CMIUtilString &vrwFileNamePath) const; + bool GetLogFilesPath(CMIUtilString &vrwFileNamePath) const; + + // Overrideable: + public: + // From CMICmnBase + /* dtor */ virtual ~CMIUtilSystemLinux(void); }; typedef CMIUtilSystemLinux CMIUtilSystem; diff --git a/tools/lldb-mi/MIUtilSystemOsx.cpp b/tools/lldb-mi/MIUtilSystemOsx.cpp index e291304789d5..f095c6212eb4 100644 --- a/tools/lldb-mi/MIUtilSystemOsx.cpp +++ b/tools/lldb-mi/MIUtilSystemOsx.cpp @@ -8,118 +8,116 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilSystemOsx.cpp +// File: MIUtilSystemOsx.cpp // -// Overview: CMIUtilSystemOsx implementation. +// Overview: CMIUtilSystemOsx implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- -#if defined( __APPLE__ ) +#if defined(__APPLE__) // In-house headers: #include "MIUtilSystemOsx.h" #include "MICmnResources.h" //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilSystemOsx constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilSystemOsx constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilSystemOsx::CMIUtilSystemOsx( void ) +CMIUtilSystemOsx::CMIUtilSystemOsx(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilSystemOsx destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilSystemOsx destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilSystemOsx::~CMIUtilSystemOsx( void ) +CMIUtilSystemOsx::~CMIUtilSystemOsx(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the OS system error message for the given system error code. -// Type: Method. -// Args: vError - (R) OS error code value. -// vrwErrorMsg - (W) The error message. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieve the OS system error message for the given system error code. +// Type: Method. +// Args: vError - (R) OS error code value. +// vrwErrorMsg - (W) The error message. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilSystemOsx::GetOSErrorMsg( const MIint vError, CMIUtilString & vrwErrorMsg ) const +bool +CMIUtilSystemOsx::GetOSErrorMsg(const MIint vError, CMIUtilString &vrwErrorMsg) const { - // Reset - vrwErrorMsg.clear(); + // Reset + vrwErrorMsg.clear(); - bool bOk = MIstatus::failure; - - // ToDo: Implement LINUX version - - return bOk; + bool bOk = MIstatus::failure; + + // ToDo: Implement LINUX version + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve if possible the OS last error description. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Error description. -// Throws: None. +// Details: Retrieve if possible the OS last error description. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Error description. +// Throws: None. //-- -CMIUtilString CMIUtilSystemOsx::GetOSLastError( void ) const +CMIUtilString +CMIUtilSystemOsx::GetOSLastError(void) const { - CMIUtilString errorMsg( "Error fn not implemented" ); - - // ToDo: Implement LINUX version - - return errorMsg; + CMIUtilString errorMsg("Error fn not implemented"); + + // ToDo: Implement LINUX version + + return errorMsg; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieves the fully qualified path for the this application. If the function -// fails the string is filled with the error message. -// Type: Method. -// Args: vrwFileNamePath - (W) The excutable's name and path or last error description. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieves the fully qualified path for the this application. If the function +// fails the string is filled with the error message. +// Type: Method. +// Args: vrwFileNamePath - (W) The excutable's name and path or last error description. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilSystemOsx::GetExecutablesPath( CMIUtilString & vrwFileNamePath ) const +bool +CMIUtilSystemOsx::GetExecutablesPath(CMIUtilString &vrwFileNamePath) const { - bool bOk = MIstatus::failure; - - // ToDo: Implement OSX version - - return bOk; + vrwFileNamePath = CMIUtilString("."); + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieves the fully qualified path for the Log file for this application. -// If the function fails the string is filled with the error message. -// Append a dummy file name on the end of the path. This will be stripped off -// later and the real log file name replaces it. -// Type: Method. -// Args: vrwFileNamePath - (W) The Log file's name and path or last error description. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieves the fully qualified path for the Log file for this application. +// If the function fails the string is filled with the error message. +// Append a dummy file name on the end of the path. This will be stripped off +// later and the real log file name replaces it. +// Type: Method. +// Args: vrwFileNamePath - (W) The Log file's name and path or last error description. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilSystemOsx::GetLogFilesPath( CMIUtilString & vrwFileNamePath ) const +bool +CMIUtilSystemOsx::GetLogFilesPath(CMIUtilString &vrwFileNamePath) const { - bool bOk = MIstatus::failure; - - // ToDo: Implement OSX version - - return bOk; + vrwFileNamePath = CMIUtilString("."); + return MIstatus::success; } #endif // #if defined( __APPLE__ ) diff --git a/tools/lldb-mi/MIUtilSystemOsx.h b/tools/lldb-mi/MIUtilSystemOsx.h index d0825c6e3441..182b0c950cd7 100644 --- a/tools/lldb-mi/MIUtilSystemOsx.h +++ b/tools/lldb-mi/MIUtilSystemOsx.h @@ -8,48 +8,48 @@ //===----------------------------------------------------------------------===// //++ -// File: CMIUtilSystemOsx.h +// File: CMIUtilSystemOsx.h // -// Overview: CMIUtilSystemOsx interface. +// Overview: CMIUtilSystemOsx interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once -#if defined( __APPLE__ ) +#if defined(__APPLE__) // In-house headers: -#include "MIUtilString.h" +#include "MIUtilString.h" //++ ============================================================================ -// Details: MI common code utility class. Used to set or retrieve information -// about the current system or user. -// *** If you change, remove or add functionality it must be replicated -// *** for the all platforms supported; Windows, OSX, LINUX -// Gotchas: None. -// Authors: Illya Rudkin 29/01/2014. -// Changes: None. +// Details: MI common code utility class. Used to set or retrieve information +// about the current system or user. +// *** If you change, remove or add functionality it must be replicated +// *** for the all platforms supported; Windows, OSX, LINUX +// Gotchas: None. +// Authors: Illya Rudkin 29/01/2014. +// Changes: None. //-- class CMIUtilSystemOsx { -// Methods: -public: - /* ctor */ CMIUtilSystemOsx( void ); - - bool GetOSErrorMsg( const MIint vError, CMIUtilString & vrwErrorMsg ) const; - CMIUtilString GetOSLastError( void ) const; - bool GetExecutablesPath( CMIUtilString & vrwFileNamePath ) const; - bool GetLogFilesPath( CMIUtilString & vrwFileNamePath ) const; - -// Overrideable: -public: - // From CMICmnBase - /* dtor */ virtual ~CMIUtilSystemOsx( void ); + // Methods: + public: + /* ctor */ CMIUtilSystemOsx(void); + + bool GetOSErrorMsg(const MIint vError, CMIUtilString &vrwErrorMsg) const; + CMIUtilString GetOSLastError(void) const; + bool GetExecutablesPath(CMIUtilString &vrwFileNamePath) const; + bool GetLogFilesPath(CMIUtilString &vrwFileNamePath) const; + + // Overrideable: + public: + // From CMICmnBase + /* dtor */ virtual ~CMIUtilSystemOsx(void); }; typedef CMIUtilSystemOsx CMIUtilSystem; diff --git a/tools/lldb-mi/MIUtilSystemWindows.cpp b/tools/lldb-mi/MIUtilSystemWindows.cpp index 5873aad0ec62..f03fa225cd90 100644 --- a/tools/lldb-mi/MIUtilSystemWindows.cpp +++ b/tools/lldb-mi/MIUtilSystemWindows.cpp @@ -8,144 +8,146 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilSystemWindows.cpp +// File: MIUtilSystemWindows.cpp // -// Overview: CMIUtilSystemWindows implementation. +// Overview: CMIUtilSystemWindows implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- -#if defined( _MSC_VER ) +#if defined(_MSC_VER) // Third party headers -#include // std::unique_ptr +#include // std::unique_ptr #include -#include // ::FormatMessage() +#include // ::FormatMessage() // In-house headers: #include "MIUtilSystemWindows.h" #include "MICmnResources.h" //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilSystemWindows constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilSystemWindows constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilSystemWindows::CMIUtilSystemWindows( void ) +CMIUtilSystemWindows::CMIUtilSystemWindows(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilSystemWindows destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilSystemWindows destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilSystemWindows::~CMIUtilSystemWindows( void ) +CMIUtilSystemWindows::~CMIUtilSystemWindows(void) { } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the OS system error message for the given system error code. -// Type: Method. -// Args: vError - (R) OS error code value. -// vrwErrorMsg - (W) The error message. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieve the OS system error message for the given system error code. +// Type: Method. +// Args: vError - (R) OS error code value. +// vrwErrorMsg - (W) The error message. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilSystemWindows::GetOSErrorMsg( const MIint vError, CMIUtilString & vrwErrorMsg ) const +bool +CMIUtilSystemWindows::GetOSErrorMsg(const MIint vError, CMIUtilString &vrwErrorMsg) const { - // Reset - vrwErrorMsg.clear(); - - const MIuint nBufLen = 1024; - std::unique_ptr< char[] > pBuffer; - pBuffer.reset( new char[ nBufLen ] ); - - // CMIUtilString Format is not used as cannot replicate the behavior of ::FormatMessage which - // can take into account locality while retrieving the error message from the system. - const int nLength = ::FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, (DWORD) vError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), - reinterpret_cast< LPTSTR >( &pBuffer[ 0 ] ), - nBufLen, nullptr ); - bool bOk = MIstatus::success; - if( nLength != 0 ) - vrwErrorMsg = &pBuffer[ 0 ]; - else - bOk = MIstatus::failure; - - return bOk; + // Reset + vrwErrorMsg.clear(); + + const MIuint nBufLen = 1024; + std::unique_ptr pBuffer; + pBuffer.reset(new char[nBufLen]); + + // CMIUtilString Format is not used as cannot replicate the behavior of ::FormatMessage which + // can take into account locality while retrieving the error message from the system. + const int nLength = ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, (DWORD)vError, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast(&pBuffer[0]), nBufLen, nullptr); + bool bOk = MIstatus::success; + if (nLength != 0) + vrwErrorMsg = &pBuffer[0]; + else + bOk = MIstatus::failure; + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve if possible the OS last error description. -// Type: Method. -// Args: None. -// Return: CMIUtilString - Error description. -// Throws: None. +// Details: Retrieve if possible the OS last error description. +// Type: Method. +// Args: None. +// Return: CMIUtilString - Error description. +// Throws: None. //-- -CMIUtilString CMIUtilSystemWindows::GetOSLastError( void ) const +CMIUtilString +CMIUtilSystemWindows::GetOSLastError(void) const { - CMIUtilString errorMsg; - const DWORD dwLastError = ::GetLastError(); - if( dwLastError != 0 ) - { - if( !GetOSErrorMsg( dwLastError, errorMsg ) ) - errorMsg = MIRSRC( IDE_OS_ERR_RETRIEVING ); - } - else - errorMsg = MIRSRC( IDE_OS_ERR_UNKNOWN ); - - return errorMsg; + CMIUtilString errorMsg; + const DWORD dwLastError = ::GetLastError(); + if (dwLastError != 0) + { + if (!GetOSErrorMsg(dwLastError, errorMsg)) + errorMsg = MIRSRC(IDE_OS_ERR_RETRIEVING); + } + else + errorMsg = MIRSRC(IDE_OS_ERR_UNKNOWN); + + return errorMsg; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieves the fully qualified path for the this application. If the function -// fails the string is filled with the error message. -// Type: Method. -// Args: vrwFileNamePath - (W) The excutable's name and path or last error description. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieves the fully qualified path for the this application. If the function +// fails the string is filled with the error message. +// Type: Method. +// Args: vrwFileNamePath - (W) The excutable's name and path or last error description. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilSystemWindows::GetExecutablesPath( CMIUtilString & vrwFileNamePath ) const +bool +CMIUtilSystemWindows::GetExecutablesPath(CMIUtilString &vrwFileNamePath) const { - bool bOk = MIstatus::success; - HMODULE hModule = ::GetModuleHandle( nullptr ); - char pPath[ MAX_PATH ]; - const DWORD nLen = ::GetModuleFileName( hModule, &pPath[ 0 ], MAX_PATH ); - const CMIUtilString strLastErr( GetOSLastError() ); - if( (nLen != 0) && (strLastErr == "Unknown OS error") ) - vrwFileNamePath = &pPath[ 0 ]; - else - { - bOk = MIstatus::failure; - vrwFileNamePath = strLastErr; - } - - return bOk; + bool bOk = MIstatus::success; + HMODULE hModule = ::GetModuleHandle(nullptr); + char pPath[MAX_PATH]; + const DWORD nLen = ::GetModuleFileName(hModule, &pPath[0], MAX_PATH); + const CMIUtilString strLastErr(GetOSLastError()); + if ((nLen != 0) && (strLastErr == "Unknown OS error")) + vrwFileNamePath = &pPath[0]; + else + { + bOk = MIstatus::failure; + vrwFileNamePath = strLastErr; + } + + return bOk; } //++ ------------------------------------------------------------------------------------ -// Details: Retrieves the fully qualified path for the Log file for this application. -// If the function fails the string is filled with the error message. -// Type: Method. -// Args: vrwFileNamePath - (W) The Log file's name and path or last error description. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Retrieves the fully qualified path for the Log file for this application. +// If the function fails the string is filled with the error message. +// Type: Method. +// Args: vrwFileNamePath - (W) The Log file's name and path or last error description. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilSystemWindows::GetLogFilesPath( CMIUtilString & vrwFileNamePath ) const +bool +CMIUtilSystemWindows::GetLogFilesPath(CMIUtilString &vrwFileNamePath) const { - return GetExecutablesPath( vrwFileNamePath ); + return GetExecutablesPath(vrwFileNamePath); } #endif // #if defined( _MSC_VER ) diff --git a/tools/lldb-mi/MIUtilSystemWindows.h b/tools/lldb-mi/MIUtilSystemWindows.h index c0d8b543a2f0..59e2de02df53 100644 --- a/tools/lldb-mi/MIUtilSystemWindows.h +++ b/tools/lldb-mi/MIUtilSystemWindows.h @@ -8,47 +8,47 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilSystemWindows.h +// File: MIUtilSystemWindows.h // -// Overview: CMIUtilSystemWindows interface. +// Overview: CMIUtilSystemWindows interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once -#if defined( _MSC_VER ) +#if defined(_MSC_VER) // In-house headers: -#include "MIUtilString.h" +#include "MIUtilString.h" //++ ============================================================================ -// Details: MI common code utility class. Used to set or retrieve information -// about the current system or user. -// *** If you change, remove or add functionality it must be replicated -// *** for the all platforms supported; Windows, OSX, LINUX -// Gotchas: None. -// Authors: Illya Rudkin 29/01/2014. -// Changes: None. +// Details: MI common code utility class. Used to set or retrieve information +// about the current system or user. +// *** If you change, remove or add functionality it must be replicated +// *** for the all platforms supported; Windows, OSX, LINUX +// Gotchas: None. +// Authors: Illya Rudkin 29/01/2014. +// Changes: None. //-- class CMIUtilSystemWindows { -// Methods: -public: - /* ctor */ CMIUtilSystemWindows( void ); - - bool GetOSErrorMsg( const MIint vError, CMIUtilString & vrwErrorMsg ) const; - CMIUtilString GetOSLastError( void ) const; - bool GetExecutablesPath( CMIUtilString & vrwFileNamePath ) const; - bool GetLogFilesPath( CMIUtilString & vrwFileNamePath ) const; - -// Overrideable: -public: - // From CMICmnBase - /* dtor */ virtual ~CMIUtilSystemWindows( void ); + // Methods: + public: + /* ctor */ CMIUtilSystemWindows(void); + + bool GetOSErrorMsg(const MIint vError, CMIUtilString &vrwErrorMsg) const; + CMIUtilString GetOSLastError(void) const; + bool GetExecutablesPath(CMIUtilString &vrwFileNamePath) const; + bool GetLogFilesPath(CMIUtilString &vrwFileNamePath) const; + + // Overrideable: + public: + // From CMICmnBase + /* dtor */ virtual ~CMIUtilSystemWindows(void); }; typedef CMIUtilSystemWindows CMIUtilSystem; diff --git a/tools/lldb-mi/MIUtilTermios.cpp b/tools/lldb-mi/MIUtilTermios.cpp index f026436e3fa3..fb71a67c8541 100644 --- a/tools/lldb-mi/MIUtilTermios.cpp +++ b/tools/lldb-mi/MIUtilTermios.cpp @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilTermios.cpp +// File: MIUtilTermios.cpp // -// Overview: Terminal setting termios functions. +// Overview: Terminal setting termios functions. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third party headers: @@ -29,40 +29,42 @@ namespace MIUtilTermios { // Instantiations: -static bool g_bOldStdinTermiosIsValid = false; // True = yes valid, false = no valid -static struct termios g_sOldStdinTermios; +static bool g_bOldStdinTermiosIsValid = false; // True = yes valid, false = no valid +static struct termios g_sOldStdinTermios; //++ ------------------------------------------------------------------------------------ -// Details: Reset the terminal settings. This function is added as an ::atexit handler -// to make sure we clean up. See StdinTerminosSet(). -// Type: Global function. -// Args: None. -// Return: None. -// Throws: None. +// Details: Reset the terminal settings. This function is added as an ::atexit handler +// to make sure we clean up. See StdinTerminosSet(). +// Type: Global function. +// Args: None. +// Return: None. +// Throws: None. //-- -void StdinTermiosReset( void ) +void +StdinTermiosReset(void) { - if( g_bOldStdinTermiosIsValid ) + if (g_bOldStdinTermiosIsValid) { g_bOldStdinTermiosIsValid = false; - ::tcsetattr( STDIN_FILENO, TCSANOW, &g_sOldStdinTermios ); + ::tcsetattr(STDIN_FILENO, TCSANOW, &g_sOldStdinTermios); } } //++ ------------------------------------------------------------------------------------ -// Details: Set the terminal settings function. StdinTermiosReset() is called when to -// reset to this to before and application exit. -// Type: Global function. -// Args: None. -// Return: None. -// Throws: None. +// Details: Set the terminal settings function. StdinTermiosReset() is called when to +// reset to this to before and application exit. +// Type: Global function. +// Args: None. +// Return: None. +// Throws: None. //-- -void StdinTermiosSet( void ) +void +StdinTermiosSet(void) { - if( ::tcgetattr( STDIN_FILENO, &g_sOldStdinTermios ) == 0 ) + if (::tcgetattr(STDIN_FILENO, &g_sOldStdinTermios) == 0) { g_bOldStdinTermiosIsValid = true; - ::atexit( StdinTermiosReset ); + ::atexit(StdinTermiosReset); } } diff --git a/tools/lldb-mi/MIUtilTermios.h b/tools/lldb-mi/MIUtilTermios.h index b38f367b68ea..f1983d64f005 100644 --- a/tools/lldb-mi/MIUtilTermios.h +++ b/tools/lldb-mi/MIUtilTermios.h @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilTermios.h +// File: MIUtilTermios.h // -// Overview: Terminal setting termios functions. +// Overview: Terminal setting termios functions. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -24,7 +24,7 @@ namespace MIUtilTermios { -extern void StdinTermiosReset( void ); -extern void StdinTermiosSet( void ); +extern void StdinTermiosReset(void); +extern void StdinTermiosSet(void); } // MIUtilTermios diff --git a/tools/lldb-mi/MIUtilThreadBaseStd.cpp b/tools/lldb-mi/MIUtilThreadBaseStd.cpp index 38f3eb4fae3b..1cf04fa5b2ae 100644 --- a/tools/lldb-mi/MIUtilThreadBaseStd.cpp +++ b/tools/lldb-mi/MIUtilThreadBaseStd.cpp @@ -8,17 +8,17 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilThreadBaseStd.cpp +// File: MIUtilThreadBaseStd.cpp // -// Overview: CMIUtilThread implementation. -// CMIUtilThreadActiveObjBase implementation. -// CMIUtilThreadMutex implementation. +// Overview: CMIUtilThread implementation. +// CMIUtilThreadActiveObjBase implementation. +// CMIUtilThreadMutex implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third Party Headers: @@ -29,271 +29,282 @@ #include "MICmnThreadMgrStd.h" //++ ------------------------------------------------------------------------------------ -// Details: Constructor. -// Type: None. -// Args: None. -// Return: None. -// Throws: None. +// Details: Constructor. +// Type: None. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilThreadActiveObjBase::CMIUtilThreadActiveObjBase( void ) -: m_references( 0 ) -, m_bHasBeenKilled( false ) +CMIUtilThreadActiveObjBase::CMIUtilThreadActiveObjBase(void) + : m_references(0) + , m_bHasBeenKilled(false) { } //++ ------------------------------------------------------------------------------------ -// Details: Destructor. -// Type: None. -// Args: None. -// Return: None. -// Throws: None. +// Details: Destructor. +// Type: None. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilThreadActiveObjBase::~CMIUtilThreadActiveObjBase( void ) +CMIUtilThreadActiveObjBase::~CMIUtilThreadActiveObjBase(void) { - // Make sure our thread is not alive before we die - m_thread.Join(); + // Make sure our thread is not alive before we die + m_thread.Join(); } //++ ------------------------------------------------------------------------------------ -// Details: Check if an object is already running. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Check if an object is already running. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilThreadActiveObjBase::ThreadIsActive( void ) +bool +CMIUtilThreadActiveObjBase::ThreadIsActive(void) { - // Create a new thread to occupy this threads Run() function - return m_thread.IsActive(); + // Create a new thread to occupy this threads Run() function + return m_thread.IsActive(); } //++ ------------------------------------------------------------------------------------ -// Details: Set up *this thread. -// Type: Mrthod. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Set up *this thread. +// Type: Mrthod. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilThreadActiveObjBase::ThreadExecute( void ) +bool +CMIUtilThreadActiveObjBase::ThreadExecute(void) { - // Create a new thread to occupy this threads Run() function - return m_thread.Start( ThreadEntry, this ); + // Create a new thread to occupy this threads Run() function + return m_thread.Start(ThreadEntry, this); } //++ ------------------------------------------------------------------------------------ -// Details: Aquire a reference to CMIUtilThreadActiveObjBase. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Aquire a reference to CMIUtilThreadActiveObjBase. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilThreadActiveObjBase::Acquire( void ) +bool +CMIUtilThreadActiveObjBase::Acquire(void) { - // Access to this function is serial - CMIUtilThreadLock serial( m_mutex ); + // Access to this function is serial + CMIUtilThreadLock serial(m_mutex); - // >0 == *this thread is alive - m_references++; + // >0 == *this thread is alive + m_references++; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Release a reference to CMIUtilThreadActiveObjBase. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Release a reference to CMIUtilThreadActiveObjBase. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilThreadActiveObjBase::Release( void ) +bool +CMIUtilThreadActiveObjBase::Release(void) { - // Access to this function is serial - CMIUtilThreadLock serial( m_mutex ); - - // 0 == kill off *this thread - m_references--; + // Access to this function is serial + CMIUtilThreadLock serial(m_mutex); - return MIstatus::success; + // 0 == kill off *this thread + m_references--; + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Force this thread to stop, regardless of references -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Force this thread to stop, regardless of references +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilThreadActiveObjBase::ThreadKill( void ) +bool +CMIUtilThreadActiveObjBase::ThreadKill(void) { - // Access to this function is serial - CMIUtilThreadLock serial( m_mutex ); + // Access to this function is serial + CMIUtilThreadLock serial(m_mutex); - // Set this thread to killed status - m_bHasBeenKilled = true; + // Set this thread to killed status + m_bHasBeenKilled = true; - return MIstatus::success; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Proxy to thread join. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilThreadActiveObjBase::ThreadJoin( void ) +bool +CMIUtilThreadActiveObjBase::ThreadJoin(void) { - return m_thread.Join(); + return m_thread.Join(); } //++ ------------------------------------------------------------------------------------ -// Details: This function is the entry point of this object thread. -// It is a trampoline to an instances operation manager. -// Type: Static method. -// Args: vpThisClass - (R) From the system (our CMIUtilThreadActiveObjBase from the ctor). -// Return: MIuint - 0 = success. -// Throws: None. +// Details: This function is the entry point of this object thread. +// It is a trampoline to an instances operation manager. +// Type: Static method. +// Args: vpThisClass - (R) From the system (our CMIUtilThreadActiveObjBase from the ctor). +// Return: MIuint - 0 = success. +// Throws: None. //-- -MIuint CMIUtilThreadActiveObjBase::ThreadEntry( void * vpThisClass ) +MIuint +CMIUtilThreadActiveObjBase::ThreadEntry(void *vpThisClass) { - // The argument is a pointer to a CMIUtilThreadActiveObjBase class - // as passed from the initialize function, so we can safely cast it. - assert( vpThisClass != nullptr ); - CMIUtilThreadActiveObjBase * pActive = reinterpret_cast< CMIUtilThreadActiveObjBase * >( vpThisClass ); + // The argument is a pointer to a CMIUtilThreadActiveObjBase class + // as passed from the initialize function, so we can safely cast it. + assert(vpThisClass != nullptr); + CMIUtilThreadActiveObjBase *pActive = reinterpret_cast(vpThisClass); - // Start the management routine of this object - pActive->ThreadManage(); + // Start the management routine of this object + pActive->ThreadManage(); - // Thread death + // Thread death return 0; } //++ ------------------------------------------------------------------------------------ -// Details: This function forms a small management routine, to handle the thread's running. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: This function forms a small management routine, to handle the thread's running. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMIUtilThreadActiveObjBase::ThreadManage( void ) +void +CMIUtilThreadActiveObjBase::ThreadManage(void) { - bool bAlive = true; - - // Infinite loop - while( bAlive ) - { - // Scope the lock while we access m_isDying - { - // Lock down access to the interface - CMIUtilThreadLock serial( m_mutex ); - - // Quit the run loop if we are dying - if( m_references == 0 ) - break; - } - // Execute the run routine - if( !ThreadRun( bAlive ) ) - // Thread's run function failed (MIstatus::failure) - break; - - // We will die if we have been signaled to die - bAlive &= !m_bHasBeenKilled; - } - - // Execute the finish routine just before we die - // to give the object a chance to clean up - ThreadFinish(); + bool bAlive = true; + + // Infinite loop + while (bAlive) + { + // Scope the lock while we access m_isDying + { + // Lock down access to the interface + CMIUtilThreadLock serial(m_mutex); + + // Quit the run loop if we are dying + if (m_references == 0) + break; + } + // Execute the run routine + if (!ThreadRun(bAlive)) + // Thread's run function failed (MIstatus::failure) + break; + + // We will die if we have been signaled to die + bAlive &= !m_bHasBeenKilled; + } + + // Execute the finish routine just before we die + // to give the object a chance to clean up + ThreadFinish(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -// -CMIUtilThread::CMIUtilThread( void ) -: m_pThread( nullptr ) +// +CMIUtilThread::CMIUtilThread(void) + : m_pThread(nullptr) { } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilThread destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilThread destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilThread::~CMIUtilThread( void ) +CMIUtilThread::~CMIUtilThread(void) { - Join(); + Join(); } //++ ------------------------------------------------------------------------------------ -// Details: Wait for thread to stop. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Wait for thread to stop. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilThread::Join( void ) +bool +CMIUtilThread::Join(void) { - if( m_pThread != nullptr ) - { - // Wait for this thread to die - m_pThread->join(); - - // Scope the thread lock while we modify the pointer - { - CMIUtilThreadLock _lock( m_mutex ); - delete m_pThread; - m_pThread = nullptr; - } - } - - return MIstatus::success; + if (m_pThread != nullptr) + { + // Wait for this thread to die + m_pThread->join(); + + // Scope the thread lock while we modify the pointer + { + CMIUtilThreadLock _lock(m_mutex); + delete m_pThread; + m_pThread = nullptr; + } + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Is the thread doing work. -// Type: Method. -// Args: None. -// Return: bool - True = Yes active, false = not active. -// Throws: None. +// Details: Is the thread doing work. +// Type: Method. +// Args: None. +// Return: bool - True = Yes active, false = not active. +// Throws: None. //-- -bool CMIUtilThread::IsActive( void ) +bool +CMIUtilThread::IsActive(void) { - // Lock while we access the thread pointer - CMIUtilThreadLock _lock( m_mutex ); - if( m_pThread == nullptr ) - return false; - else - return true; + // Lock while we access the thread pointer + CMIUtilThreadLock _lock(m_mutex); + if (m_pThread == nullptr) + return false; + else + return true; } //++ ------------------------------------------------------------------------------------ -// Details: Set up *this thread. -// Type: Method. -// Args: vpFn (R) - Function pointer to thread's main function. -// vpArg (R) - Pointer arguments to pass to the thread. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Set up *this thread. +// Type: Method. +// Args: vpFn (R) - Function pointer to thread's main function. +// vpArg (R) - Pointer arguments to pass to the thread. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMIUtilThread::Start( FnThreadProc vpFn, void * vpArg ) +bool +CMIUtilThread::Start(FnThreadProc vpFn, void *vpArg) { - // Create the std thread, which starts immediately - m_pThread = new std::thread( vpFn, vpArg ); - - // We expect to always be able to create one - assert( m_pThread != nullptr ); - - return MIstatus::success; + // Create the std thread, which starts immediately + m_pThread = new std::thread(vpFn, vpArg); + + // We expect to always be able to create one + assert(m_pThread != nullptr); + + return MIstatus::success; } //--------------------------------------------------------------------------------------- @@ -301,39 +312,41 @@ bool CMIUtilThread::Start( FnThreadProc vpFn, void * vpArg ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: Take resource. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: Take resource. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMIUtilThreadMutex::Lock( void ) +void +CMIUtilThreadMutex::Lock(void) { - m_mutex.lock(); + m_mutex.lock(); } - + //++ ------------------------------------------------------------------------------------ -// Details: Release resource. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: Release resource. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMIUtilThreadMutex::Unlock( void ) +void +CMIUtilThreadMutex::Unlock(void) { - m_mutex.unlock(); + m_mutex.unlock(); } //++ ------------------------------------------------------------------------------------ -// Details: Take resource if available. Immediately return in either case. -// Type: Method. -// Args: None. -// Return: True - mutex has been locked. -// False - mutex could not be locked. -// Throws: None. +// Details: Take resource if available. Immediately return in either case. +// Type: Method. +// Args: None. +// Return: True - mutex has been locked. +// False - mutex could not be locked. +// Throws: None. //-- -bool CMIUtilThreadMutex::TryLock( void ) +bool +CMIUtilThreadMutex::TryLock(void) { - return m_mutex.try_lock(); + return m_mutex.try_lock(); } - diff --git a/tools/lldb-mi/MIUtilThreadBaseStd.h b/tools/lldb-mi/MIUtilThreadBaseStd.h index 277e14c0fc88..e3cf5083011d 100644 --- a/tools/lldb-mi/MIUtilThreadBaseStd.h +++ b/tools/lldb-mi/MIUtilThreadBaseStd.h @@ -8,18 +8,18 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilThreadBaseStd.h +// File: MIUtilThreadBaseStd.h // -// Overview: CMIUtilThread interface. -// CMIUtilThreadActiveObjBase interface. -// CMIUtilThreadMutex interface. -// CMIUtilThreadLock interface. +// Overview: CMIUtilThread interface. +// CMIUtilThreadActiveObjBase interface. +// CMIUtilThreadMutex interface. +// CMIUtilThreadLock interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- #pragma once @@ -36,135 +36,148 @@ #include "MIUtilString.h" //++ ============================================================================ -// Details: MI common code utility class. Handle thread mutual exclusion. -// Embed Mutexes in your Active Object and then use them through Locks. -// Gotchas: None. -// Authors: Aidan Dodds 10/03/2014. -// Changes: None. +// Details: MI common code utility class. Handle thread mutual exclusion. +// Embed Mutexes in your Active Object and then use them through Locks. +// Gotchas: None. +// Authors: Aidan Dodds 10/03/2014. +// Changes: None. //-- class CMIUtilThreadMutex { - // Methods: -public: - /* ctor */ CMIUtilThreadMutex( void ) { }; - // - void Lock( void ); // Wait until mutex can be obtained - void Unlock( void ); // Release the mutex - bool TryLock( void ); // Gain the lock if available - -// Overrideable: -public: - // From CMICmnBase - /* dtor */ virtual ~CMIUtilThreadMutex( void ) { }; - -// Attributes: -private: - std::recursive_mutex m_mutex; + // Methods: + public: + /* ctor */ CMIUtilThreadMutex(void){}; + // + void + Lock(void); // Wait until mutex can be obtained + void + Unlock(void); // Release the mutex + bool + TryLock(void); // Gain the lock if available + + // Overrideable: + public: + // From CMICmnBase + /* dtor */ virtual ~CMIUtilThreadMutex(void){}; + + // Attributes: + private: + std::recursive_mutex m_mutex; }; //++ ============================================================================ -// Details: MI common code utility class. Thread object. -// Gotchas: None. -// Authors: Aidan Dodds 10/03/2014. -// Changes: None. +// Details: MI common code utility class. Thread object. +// Gotchas: None. +// Authors: Aidan Dodds 10/03/2014. +// Changes: None. //-- class CMIUtilThread { -// Typedef: -public: - typedef MIuint (* FnThreadProc) (void * vpThisClass); - -// Methods: -public: - /* ctor */ CMIUtilThread( void ); - // - bool Start( FnThreadProc vpFn, void * vpArg ); // Start execution of this thread - bool Join( void ); // Wait for this thread to stop - bool IsActive( void ); // Returns true if this thread is running - -// Overrideable: -public: - /* dtor */ virtual ~CMIUtilThread( void ); - -// Methods: -private: - CMIUtilThreadMutex m_mutex; - std::thread * m_pThread; + // Typedef: + public: + typedef MIuint (*FnThreadProc)(void *vpThisClass); + + // Methods: + public: + /* ctor */ CMIUtilThread(void); + // + bool + Start(FnThreadProc vpFn, void *vpArg); // Start execution of this thread + bool + Join(void); // Wait for this thread to stop + bool + IsActive(void); // Returns true if this thread is running + + // Overrideable: + public: + /* dtor */ virtual ~CMIUtilThread(void); + + // Methods: + private: + CMIUtilThreadMutex m_mutex; + std::thread *m_pThread; }; //++ ============================================================================ -// Details: MI common code utility class. Base class for a worker thread active -// object. Runs an 'captive thread'. -// Gotchas: None. -// Authors: Aidan Dodds 10/03/2014.. -// Changes: None. +// Details: MI common code utility class. Base class for a worker thread active +// object. Runs an 'captive thread'. +// Gotchas: None. +// Authors: Aidan Dodds 10/03/2014.. +// Changes: None. //-- class CMIUtilThreadActiveObjBase { -// Methods: -public: - /* ctor */ CMIUtilThreadActiveObjBase( void ); - // - bool Acquire( void ); // Obtain a reference to this object - bool Release( void ); // Release a reference to this object - bool ThreadIsActive( void ); // Return true if this object is running - bool ThreadJoin( void ); // Wait for this thread to stop running - bool ThreadKill( void ); // Force this thread to stop, regardless of references - bool ThreadExecute( void ); // Start this objects execution in another thread - void ThreadManage( void ); - -// Overrideable: -public: - /* dtor */ virtual ~CMIUtilThreadActiveObjBase( void ); - // - // Each thread object must supple a unique name that can be used to locate it - virtual const CMIUtilString & ThreadGetName( void ) const = 0; - -// Statics: -protected: - static MIuint ThreadEntry( void * vpThisClass ); // Thread entry point - -// Overrideable: -protected: - virtual bool ThreadRun( bool &vrIsAlive ) = 0; // Call the main worker method - virtual bool ThreadFinish( void ) = 0; // Finish of what you were doing - -// Attributes: -protected: - volatile MIuint m_references; // Stores the current lifetime state of this thread, 0 = running, > 0 = shutting down - volatile bool m_bHasBeenKilled; // Set to true when this thread has been killed - CMIUtilThread m_thread; // The execution thread - CMIUtilThreadMutex m_mutex; // This mutex allows us to safely communicate with this thread object across the interface from multiple threads + // Methods: + public: + /* ctor */ CMIUtilThreadActiveObjBase(void); + // + bool + Acquire(void); // Obtain a reference to this object + bool + Release(void); // Release a reference to this object + bool + ThreadIsActive(void); // Return true if this object is running + bool + ThreadJoin(void); // Wait for this thread to stop running + bool + ThreadKill(void); // Force this thread to stop, regardless of references + bool + ThreadExecute(void); // Start this objects execution in another thread + void ThreadManage(void); + + // Overrideable: + public: + /* dtor */ virtual ~CMIUtilThreadActiveObjBase(void); + // + // Each thread object must supple a unique name that can be used to locate it + virtual const CMIUtilString &ThreadGetName(void) const = 0; + + // Statics: + protected: + static MIuint + ThreadEntry(void *vpThisClass); // Thread entry point + + // Overrideable: + protected: + virtual bool + ThreadRun(bool &vrIsAlive) = 0; // Call the main worker method + virtual bool + ThreadFinish(void) = 0; // Finish of what you were doing + + // Attributes: + protected: + volatile MIuint m_references; // Stores the current lifetime state of this thread, 0 = running, > 0 = shutting down + volatile bool m_bHasBeenKilled; // Set to true when this thread has been killed + CMIUtilThread m_thread; // The execution thread + CMIUtilThreadMutex + m_mutex; // This mutex allows us to safely communicate with this thread object across the interface from multiple threads }; //++ ============================================================================ -// Details: MI common code utility class. Handle thread resource locking. -// Put Locks inside all the methods of your Active Object that access -// data shared with the captive thread. -// Gotchas: None. -// Authors: Aidan Dodds 10/03/2014. -// Changes: None. +// Details: MI common code utility class. Handle thread resource locking. +// Put Locks inside all the methods of your Active Object that access +// data shared with the captive thread. +// Gotchas: None. +// Authors: Aidan Dodds 10/03/2014. +// Changes: None. //-- class CMIUtilThreadLock { -// Methods: -public: - /* ctor */ - CMIUtilThreadLock( CMIUtilThreadMutex & vMutex ) - : m_rMutex( vMutex ) - { - m_rMutex.Lock(); - } - -// Overrideable: -public: - /* dtor */ - virtual ~CMIUtilThreadLock( void ) - { - m_rMutex.Unlock(); - } - -// Attributes: -private: - CMIUtilThreadMutex & m_rMutex; + // Methods: + public: + /* ctor */ + CMIUtilThreadLock(CMIUtilThreadMutex &vMutex) + : m_rMutex(vMutex) + { + m_rMutex.Lock(); + } + + // Overrideable: + public: + /* dtor */ + virtual ~CMIUtilThreadLock(void) { m_rMutex.Unlock(); } + + // Attributes: + private: + CMIUtilThreadMutex &m_rMutex; }; diff --git a/tools/lldb-mi/MIUtilVariant.cpp b/tools/lldb-mi/MIUtilVariant.cpp index 1c9ea1c9697f..fcf1ca8868a9 100644 --- a/tools/lldb-mi/MIUtilVariant.cpp +++ b/tools/lldb-mi/MIUtilVariant.cpp @@ -8,157 +8,161 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilVariant.cpp +// File: MIUtilVariant.cpp // -// Overview: CMIUtilVariant implementation. +// Overview: CMIUtilVariant implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Gotchas: See CMIUtilVariant class description. +// Gotchas: See CMIUtilVariant class description. // -// Copyright: None. +// Copyright: None. //-- // In-house headers: -#include "MIUtilVariant.h" +#include "MIUtilVariant.h" //++ ------------------------------------------------------------------------------------ -// Details: CDataObjectBase constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CDataObjectBase constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilVariant::CDataObjectBase::CDataObjectBase( void ) +CMIUtilVariant::CDataObjectBase::CDataObjectBase(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CDataObjectBase copy constructor. -// Type: Method. -// Args: vrOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: CDataObjectBase copy constructor. +// Type: Method. +// Args: vrOther - (R) The other object. +// Return: None. +// Throws: None. //-- -CMIUtilVariant::CDataObjectBase::CDataObjectBase( const CDataObjectBase & vrOther ) +CMIUtilVariant::CDataObjectBase::CDataObjectBase(const CDataObjectBase &vrOther) { - MIunused( vrOther ); + MIunused(vrOther); } //++ ------------------------------------------------------------------------------------ -// Details: CDataObjectBase copy constructor. -// Type: Method. -// Args: vrOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: CDataObjectBase copy constructor. +// Type: Method. +// Args: vrOther - (R) The other object. +// Return: None. +// Throws: None. //-- -CMIUtilVariant::CDataObjectBase::CDataObjectBase( CDataObjectBase & vrOther ) +CMIUtilVariant::CDataObjectBase::CDataObjectBase(CDataObjectBase &vrOther) { - MIunused( vrOther ); + MIunused(vrOther); } //++ ------------------------------------------------------------------------------------ -// Details: CDataObjectBase move constructor. -// Type: Method. -// Args: vrwOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: CDataObjectBase move constructor. +// Type: Method. +// Args: vrwOther - (R) The other object. +// Return: None. +// Throws: None. //-- -CMIUtilVariant::CDataObjectBase::CDataObjectBase( CDataObjectBase && vrwOther ) +CMIUtilVariant::CDataObjectBase::CDataObjectBase(CDataObjectBase &&vrwOther) { - MIunused( vrwOther ); + MIunused(vrwOther); } //++ ------------------------------------------------------------------------------------ -// Details: CDataObjectBase destructor. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CDataObjectBase destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilVariant::CDataObjectBase::~CDataObjectBase( void ) +CMIUtilVariant::CDataObjectBase::~CDataObjectBase(void) { - Destroy(); + Destroy(); } //++ ------------------------------------------------------------------------------------ -// Details: CDataObjectBase copy assignment. -// Type: Method. -// Args: vrOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: CDataObjectBase copy assignment. +// Type: Method. +// Args: vrOther - (R) The other object. +// Return: None. +// Throws: None. //-- -CMIUtilVariant::CDataObjectBase & CMIUtilVariant::CDataObjectBase::operator= ( const CDataObjectBase & vrOther ) +CMIUtilVariant::CDataObjectBase &CMIUtilVariant::CDataObjectBase::operator=(const CDataObjectBase &vrOther) { - Copy( vrOther ); - return *this; + Copy(vrOther); + return *this; } //++ ------------------------------------------------------------------------------------ -// Details: CDataObjectBase move assignment. -// Type: Method. -// Args: vrwOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: CDataObjectBase move assignment. +// Type: Method. +// Args: vrwOther - (R) The other object. +// Return: None. +// Throws: None. //-- -CMIUtilVariant::CDataObjectBase & CMIUtilVariant::CDataObjectBase::operator= ( CDataObjectBase && vrwOther ) +CMIUtilVariant::CDataObjectBase &CMIUtilVariant::CDataObjectBase::operator=(CDataObjectBase &&vrwOther) { - Copy( vrwOther ); - vrwOther.Destroy(); - return *this; + Copy(vrwOther); + vrwOther.Destroy(); + return *this; } //++ ------------------------------------------------------------------------------------ -// Details: Create a new copy of *this class. -// Type: Overrideable. -// Args: None. -// Return: CDataObjectBase * - Pointer to a new object. -// Throws: None. +// Details: Create a new copy of *this class. +// Type: Overrideable. +// Args: None. +// Return: CDataObjectBase * - Pointer to a new object. +// Throws: None. //-- -CMIUtilVariant::CDataObjectBase * CMIUtilVariant::CDataObjectBase::CreateCopyOfSelf( void ) +CMIUtilVariant::CDataObjectBase * +CMIUtilVariant::CDataObjectBase::CreateCopyOfSelf(void) { - // Override to implement copying of variant's data object - return new CDataObjectBase(); + // Override to implement copying of variant's data object + return new CDataObjectBase(); } //++ ------------------------------------------------------------------------------------ -// Details: Determine if *this object is a derived from CDataObjectBase. -// Type: Overrideable. -// Args: None. -// Return: bool - True = *this is derived from CDataObjectBase, false = *this is instance of the this base class. -// Throws: None. +// Details: Determine if *this object is a derived from CDataObjectBase. +// Type: Overrideable. +// Args: None. +// Return: bool - True = *this is derived from CDataObjectBase, false = *this is instance of the this base class. +// Throws: None. //-- -bool CMIUtilVariant::CDataObjectBase::GetIsDerivedClass( void ) const +bool +CMIUtilVariant::CDataObjectBase::GetIsDerivedClass(void) const { - // Override to in the derived class and return true - return false; + // Override to in the derived class and return true + return false; } //++ ------------------------------------------------------------------------------------ -// Details: Perform a bitwise copy of *this object. -// Type: Overrideable. -// Args: vrOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: Perform a bitwise copy of *this object. +// Type: Overrideable. +// Args: vrOther - (R) The other object. +// Return: None. +// Throws: None. //-- -void CMIUtilVariant::CDataObjectBase::Copy( const CDataObjectBase & vrOther ) +void +CMIUtilVariant::CDataObjectBase::Copy(const CDataObjectBase &vrOther) { - // Override to implement - MIunused( vrOther ); + // Override to implement + MIunused(vrOther); } //++ ------------------------------------------------------------------------------------ -// Details: Release any resources used by *this object. -// Type: Overrideable. -// Args: None. -// Return: None. -// Throws: None. +// Details: Release any resources used by *this object. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMIUtilVariant::CDataObjectBase::Destroy( void ) +void +CMIUtilVariant::CDataObjectBase::Destroy(void) { - // Do nothing - override to implement + // Do nothing - override to implement } //--------------------------------------------------------------------------------------- @@ -166,87 +170,82 @@ void CMIUtilVariant::CDataObjectBase::Destroy( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CDataObject copy constructor. -// Type: Method. -// Args: T - The object's type. -// vrOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: CDataObject copy constructor. +// Type: Method. +// Args: T - The object's type. +// vrOther - (R) The other object. +// Return: None. +// Throws: None. //-- -template< typename T > -CMIUtilVariant::CDataObject< T >::CDataObject( const CDataObject & vrOther ) +template CMIUtilVariant::CDataObject::CDataObject(const CDataObject &vrOther) { - if( this == &vrOther ) - return; - Copy( vrOther ); + if (this == &vrOther) + return; + Copy(vrOther); } //++ ------------------------------------------------------------------------------------ -// Details: CDataObject copy constructor. -// Type: Method. -// Args: T - The object's type. -// vrOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: CDataObject copy constructor. +// Type: Method. +// Args: T - The object's type. +// vrOther - (R) The other object. +// Return: None. +// Throws: None. //-- -template< typename T > -CMIUtilVariant::CDataObject< T >::CDataObject( CDataObject & vrOther ) +template CMIUtilVariant::CDataObject::CDataObject(CDataObject &vrOther) { - if( this == &vrOther ) - return; - Copy( vrOther ); + if (this == &vrOther) + return; + Copy(vrOther); } //++ ------------------------------------------------------------------------------------ -// Details: CDataObject move constructor. -// Type: Method. -// Args: T - The object's type. -// vrwOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: CDataObject move constructor. +// Type: Method. +// Args: T - The object's type. +// vrwOther - (R) The other object. +// Return: None. +// Throws: None. //-- -template< typename T > -CMIUtilVariant::CDataObject< T >::CDataObject( CDataObject && vrwOther ) +template CMIUtilVariant::CDataObject::CDataObject(CDataObject &&vrwOther) { - if( this == &vrwOther ) - return; - Copy( vrwOther ); - vrwOther.Destroy(); + if (this == &vrwOther) + return; + Copy(vrwOther); + vrwOther.Destroy(); } //++ ------------------------------------------------------------------------------------ -// Details: CDataObject copy assignment. -// Type: Method. -// Args: T - The object's type. -// vrOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: CDataObject copy assignment. +// Type: Method. +// Args: T - The object's type. +// vrOther - (R) The other object. +// Return: None. +// Throws: None. //-- -template< typename T > -CMIUtilVariant::CDataObject< T > & CMIUtilVariant::CDataObject< T >::operator= ( const CDataObject & vrOther ) +template CMIUtilVariant::CDataObject &CMIUtilVariant::CDataObject::operator=(const CDataObject &vrOther) { - if( this == &vrOther ) - return *this; - Copy( vrOther ); - return *this; + if (this == &vrOther) + return *this; + Copy(vrOther); + return *this; } //++ ------------------------------------------------------------------------------------ -// Details: CDataObject move assignment. -// Type: Method. -// Args: T - The object's type. -// vrwOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: CDataObject move assignment. +// Type: Method. +// Args: T - The object's type. +// vrwOther - (R) The other object. +// Return: None. +// Throws: None. //-- -template< typename T > -CMIUtilVariant::CDataObject< T > & CMIUtilVariant::CDataObject< T >::operator= ( CDataObject && vrwOther ) +template CMIUtilVariant::CDataObject &CMIUtilVariant::CDataObject::operator=(CDataObject &&vrwOther) { - if( this == &vrwOther ) - return *this; - Copy( vrwOther ); - vrwOther.Destroy(); - return *this; + if (this == &vrwOther) + return *this; + Copy(vrwOther); + vrwOther.Destroy(); + return *this; } //--------------------------------------------------------------------------------------- @@ -254,139 +253,140 @@ CMIUtilVariant::CDataObject< T > & CMIUtilVariant::CDataObject< T >::operator= ( //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilVariant constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilVariant constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilVariant::CMIUtilVariant( void ) -: m_pDataObject( nullptr ) +CMIUtilVariant::CMIUtilVariant(void) + : m_pDataObject(nullptr) { } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilVariant copy constructor. -// Type: Method. -// Args: vrOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: CMIUtilVariant copy constructor. +// Type: Method. +// Args: vrOther - (R) The other object. +// Return: None. +// Throws: None. //-- -CMIUtilVariant::CMIUtilVariant( const CMIUtilVariant & vrOther ) -: m_pDataObject( nullptr ) +CMIUtilVariant::CMIUtilVariant(const CMIUtilVariant &vrOther) + : m_pDataObject(nullptr) { - if( this == &vrOther ) - return; + if (this == &vrOther) + return; - Copy( vrOther ); + Copy(vrOther); } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilVariant copy constructor. -// Type: Method. -// Args: vrOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: CMIUtilVariant copy constructor. +// Type: Method. +// Args: vrOther - (R) The other object. +// Return: None. +// Throws: None. //-- -CMIUtilVariant::CMIUtilVariant( CMIUtilVariant & vrOther ) -: m_pDataObject( nullptr ) +CMIUtilVariant::CMIUtilVariant(CMIUtilVariant &vrOther) + : m_pDataObject(nullptr) { - if( this == &vrOther ) - return; + if (this == &vrOther) + return; - Copy( vrOther ); + Copy(vrOther); } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilVariant move constructor. -// Type: Method. -// Args: vrwOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: CMIUtilVariant move constructor. +// Type: Method. +// Args: vrwOther - (R) The other object. +// Return: None. +// Throws: None. //-- -CMIUtilVariant::CMIUtilVariant( CMIUtilVariant && vrwOther ) -: m_pDataObject( nullptr ) +CMIUtilVariant::CMIUtilVariant(CMIUtilVariant &&vrwOther) + : m_pDataObject(nullptr) { - if( this == &vrwOther ) - return; + if (this == &vrwOther) + return; - Copy( vrwOther ); - vrwOther.Destroy(); + Copy(vrwOther); + vrwOther.Destroy(); } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilVariant destructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMIUtilVariant destructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMIUtilVariant::~CMIUtilVariant( void ) +CMIUtilVariant::~CMIUtilVariant(void) { - Destroy(); + Destroy(); } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilVariant copy assignment. -// Type: Method. -// Args: vrOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: CMIUtilVariant copy assignment. +// Type: Method. +// Args: vrOther - (R) The other object. +// Return: None. +// Throws: None. //-- -CMIUtilVariant & CMIUtilVariant::operator= ( const CMIUtilVariant & vrOther ) +CMIUtilVariant &CMIUtilVariant::operator=(const CMIUtilVariant &vrOther) { - if( this == &vrOther ) - return *this; + if (this == &vrOther) + return *this; - Copy( vrOther ); - return *this; + Copy(vrOther); + return *this; } //++ ------------------------------------------------------------------------------------ -// Details: CMIUtilVariant move assignment. -// Type: Method. -// Args: vrwOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: CMIUtilVariant move assignment. +// Type: Method. +// Args: vrwOther - (R) The other object. +// Return: None. +// Throws: None. //-- -CMIUtilVariant & CMIUtilVariant::operator= ( CMIUtilVariant && vrwOther ) +CMIUtilVariant &CMIUtilVariant::operator=(CMIUtilVariant &&vrwOther) { - if( this == &vrwOther ) - return *this; + if (this == &vrwOther) + return *this; - Copy( vrwOther ); - vrwOther.Destroy(); - return *this; + Copy(vrwOther); + vrwOther.Destroy(); + return *this; } //++ ------------------------------------------------------------------------------------ -// Details: Release the resources used by *this object. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: Release the resources used by *this object. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -void CMIUtilVariant::Destroy( void ) +void +CMIUtilVariant::Destroy(void) { - if( m_pDataObject != nullptr ) - delete m_pDataObject; - m_pDataObject = nullptr; + if (m_pDataObject != nullptr) + delete m_pDataObject; + m_pDataObject = nullptr; } //++ ------------------------------------------------------------------------------------ -// Details: Bitwise copy another data object to *this variant object. -// Type: Method. -// Args: vrOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: Bitwise copy another data object to *this variant object. +// Type: Method. +// Args: vrOther - (R) The other object. +// Return: None. +// Throws: None. //-- -void CMIUtilVariant::Copy( const CMIUtilVariant & vrOther ) +void +CMIUtilVariant::Copy(const CMIUtilVariant &vrOther) { - Destroy(); - - if( vrOther.m_pDataObject != nullptr ) - { - m_pDataObject = vrOther.m_pDataObject->CreateCopyOfSelf(); - } -} + Destroy(); + if (vrOther.m_pDataObject != nullptr) + { + m_pDataObject = vrOther.m_pDataObject->CreateCopyOfSelf(); + } +} diff --git a/tools/lldb-mi/MIUtilVariant.h b/tools/lldb-mi/MIUtilVariant.h index 3cb59796e5c0..aa1604ab6ff9 100644 --- a/tools/lldb-mi/MIUtilVariant.h +++ b/tools/lldb-mi/MIUtilVariant.h @@ -8,131 +8,131 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilVariant.h +// File: MIUtilVariant.h // -// Overview: CMIUtilVariant interface. +// Overview: CMIUtilVariant interface. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Gotchas: See CMIUtilVariant class description. +// Gotchas: See CMIUtilVariant class description. // -// Copyright: None. +// Copyright: None. //-- #pragma once // In-house headers: -#include "MIDataTypes.h" +#include "MIDataTypes.h" //++ ============================================================================ -// Details: MI common code utility class. The class implements behaviour of a -// variant object which holds any data object of type T. A copy of the -// data object specified is made and stored in *this wrapper. When the -// *this object is destroyed the data object hold within calls its -// destructor should it have one. -// Gotchas: None. -// Authors: Illya Rudkin 18/06/2014. -// Changes: None. +// Details: MI common code utility class. The class implements behaviour of a +// variant object which holds any data object of type T. A copy of the +// data object specified is made and stored in *this wrapper. When the +// *this object is destroyed the data object hold within calls its +// destructor should it have one. +// Gotchas: None. +// Authors: Illya Rudkin 18/06/2014. +// Changes: None. //-- class CMIUtilVariant { -// Methods: -public: - /* ctor */ CMIUtilVariant( void ); - /* ctor */ CMIUtilVariant( const CMIUtilVariant & vrOther ); - /* ctor */ CMIUtilVariant( CMIUtilVariant & vrOther ); - /* ctor */ CMIUtilVariant( CMIUtilVariant && vrwOther ); - /* dtor */ ~CMIUtilVariant( void ); - - template< typename T > - void Set( const T & vArg ); - template< typename T > - T * Get( void ) const; + // Methods: + public: + /* ctor */ CMIUtilVariant(void); + /* ctor */ CMIUtilVariant(const CMIUtilVariant &vrOther); + /* ctor */ CMIUtilVariant(CMIUtilVariant &vrOther); + /* ctor */ CMIUtilVariant(CMIUtilVariant &&vrwOther); + /* dtor */ ~CMIUtilVariant(void); - CMIUtilVariant & operator= ( const CMIUtilVariant & vrOther ); - CMIUtilVariant & operator= ( CMIUtilVariant && vrwOther ); + template void Set(const T &vArg); + template T *Get(void) const; -// Classes: -private: - //++ ---------------------------------------------------------------------- - // Details: Base class wrapper to hold the variant's data object when - // assigned to it by the Set() function. Do not use the CDataObjectBase - // to create objects, use only CDataObjectBase derived objects, - // see CDataObject() class. - //-- - class CDataObjectBase - { - // Methods: - public: - /* ctor */ CDataObjectBase( void ); - /* ctor */ CDataObjectBase( const CDataObjectBase & vrOther ); - /* ctor */ CDataObjectBase( CDataObjectBase & vrOther ); - /* ctor */ CDataObjectBase( CDataObjectBase && vrwOther ); - // - CDataObjectBase & operator= ( const CDataObjectBase & vrOther ) ; - CDataObjectBase & operator= ( CDataObjectBase && vrwOther ) ; - - // Overrideable: - public: - virtual ~CDataObjectBase( void ); - virtual CDataObjectBase * CreateCopyOfSelf( void ); - virtual bool GetIsDerivedClass( void ) const; + CMIUtilVariant &operator=(const CMIUtilVariant &vrOther); + CMIUtilVariant &operator=(CMIUtilVariant &&vrwOther); - // Overrideable: - protected: - virtual void Copy( const CDataObjectBase & vrOther ); - virtual void Destroy( void ); - }; + // Classes: + private: + //++ ---------------------------------------------------------------------- + // Details: Base class wrapper to hold the variant's data object when + // assigned to it by the Set() function. Do not use the CDataObjectBase + // to create objects, use only CDataObjectBase derived objects, + // see CDataObject() class. + //-- + class CDataObjectBase + { + // Methods: + public: + /* ctor */ CDataObjectBase(void); + /* ctor */ CDataObjectBase(const CDataObjectBase &vrOther); + /* ctor */ CDataObjectBase(CDataObjectBase &vrOther); + /* ctor */ CDataObjectBase(CDataObjectBase &&vrwOther); + // + CDataObjectBase &operator=(const CDataObjectBase &vrOther); + CDataObjectBase &operator=(CDataObjectBase &&vrwOther); - //++ ---------------------------------------------------------------------- - // Details: Derived from CDataObjectBase, this class is the wrapper for the - // data object as it has an aggregate of type T which is a copy - // of the data object assigned to the variant object. - //-- - template< typename T > - class CDataObject : public CDataObjectBase - { - // Methods: - public: - /* ctor */ CDataObject( void ); - /* ctor */ CDataObject( const T & vArg ); - /* ctor */ CDataObject( const CDataObject & vrOther ); - /* ctor */ CDataObject( CDataObject & vrOther ); - /* ctor */ CDataObject( CDataObject && vrwOther ); - // - CDataObject & operator= ( const CDataObject & vrOther ); - CDataObject & operator= ( CDataObject && vrwOther ); - // - T & GetDataObject( void ); + // Overrideable: + public: + virtual ~CDataObjectBase(void); + virtual CDataObjectBase *CreateCopyOfSelf(void); + virtual bool GetIsDerivedClass(void) const; - // Overridden: - public: - // From CDataObjectBase - virtual ~CDataObject( void ); - virtual CDataObjectBase * CreateCopyOfSelf( void ); - virtual bool GetIsDerivedClass( void ) const; + // Overrideable: + protected: + virtual void Copy(const CDataObjectBase &vrOther); + virtual void Destroy(void); + }; - // Overridden: - private: - // From CDataObjectBase - virtual void Copy( const CDataObject & vrOther ); - virtual void Destroy( void ); + //++ ---------------------------------------------------------------------- + // Details: Derived from CDataObjectBase, this class is the wrapper for the + // data object as it has an aggregate of type T which is a copy + // of the data object assigned to the variant object. + //-- + template class CDataObject : public CDataObjectBase + { + // Methods: + public: + /* ctor */ CDataObject(void); + /* ctor */ CDataObject(const T &vArg); + /* ctor */ CDataObject(const CDataObject &vrOther); + /* ctor */ CDataObject(CDataObject &vrOther); + /* ctor */ CDataObject(CDataObject &&vrwOther); + // + CDataObject &operator=(const CDataObject &vrOther); + CDataObject &operator=(CDataObject &&vrwOther); + // + T &GetDataObject(void); - // Attributes: - private: - T m_dataObj; - }; + // Overridden: + public: + // From CDataObjectBase + virtual ~CDataObject(void); + virtual CDataObjectBase *CreateCopyOfSelf(void); + virtual bool GetIsDerivedClass(void) const; -// Methods -private: - void Destroy( void ); - void Copy( const CMIUtilVariant & vrOther ); + // Overrideable: + private: + virtual void Duplicate(const CDataObject &vrOther); -// Attributes: -private: - CDataObjectBase * m_pDataObject; + // Overridden: + private: + // From CDataObjectBase + virtual void Destroy(void); + + // Attributes: + private: + T m_dataObj; + }; + + // Methods + private: + void Destroy(void); + void Copy(const CMIUtilVariant &vrOther); + + // Attributes: + private: + CDataObjectBase *m_pDataObject; }; //--------------------------------------------------------------------------------------- @@ -140,112 +140,114 @@ private: //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: CDataObject constructor. -// Type: Method. -// Args: T - The object's type. -// Return: None. -// Throws: None. +// Details: CDataObject constructor. +// Type: Method. +// Args: T - The object's type. +// Return: None. +// Throws: None. //-- -template< typename T > -CMIUtilVariant::CDataObject< T >::CDataObject( void ) +template CMIUtilVariant::CDataObject::CDataObject(void) { } //++ ------------------------------------------------------------------------------------ -// Details: CDataObject constructor. -// Type: Method. -// Args: T - The object's type. -// vArg - (R) The data object to be stored in the variant object. -// Return: None. -// Throws: None. +// Details: CDataObject constructor. +// Type: Method. +// Args: T - The object's type. +// vArg - (R) The data object to be stored in the variant object. +// Return: None. +// Throws: None. //-- -template< typename T > -CMIUtilVariant::CDataObject< T >::CDataObject( const T & vArg ) +template CMIUtilVariant::CDataObject::CDataObject(const T &vArg) { - m_dataObj = vArg; + m_dataObj = vArg; } //++ ------------------------------------------------------------------------------------ -// Details: CDataObject destructor. -// Type: Overridden. -// Args: T - The object's type. -// Return: None. -// Throws: None. +// Details: CDataObject destructor. +// Type: Overridden. +// Args: T - The object's type. +// Return: None. +// Throws: None. //-- -template< typename T > -CMIUtilVariant::CDataObject< T >::~CDataObject( void ) +template CMIUtilVariant::CDataObject::~CDataObject(void) { - Destroy(); + Destroy(); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the data object hold by *this object wrapper. -// Type: Method. -// Args: T - The object's type. -// Return: T & - Reference to the data object. -// Throws: None. +// Details: Retrieve the data object hold by *this object wrapper. +// Type: Method. +// Args: T - The object's type. +// Return: T & - Reference to the data object. +// Throws: None. //-- -template< typename T > -T & CMIUtilVariant::CDataObject< T >::GetDataObject( void ) +template +T & +CMIUtilVariant::CDataObject::GetDataObject(void) { - return m_dataObj; + return m_dataObj; } //++ ------------------------------------------------------------------------------------ -// Details: Create a new copy of *this class. -// Type: Overridden. -// Args: T - The object's type. -// Return: CDataObjectBase * - Pointer to a new object. -// Throws: None. +// Details: Create a new copy of *this class. +// Type: Overridden. +// Args: T - The object's type. +// Return: CDataObjectBase * - Pointer to a new object. +// Throws: None. //-- -template< typename T > -CMIUtilVariant::CDataObjectBase * CMIUtilVariant::CDataObject< T >::CreateCopyOfSelf( void ) +template +CMIUtilVariant::CDataObjectBase * +CMIUtilVariant::CDataObject::CreateCopyOfSelf(void) { - CDataObject * pCopy = new CDataObject< T >( m_dataObj ); - - return pCopy; + CDataObject *pCopy = new CDataObject(m_dataObj); + + return pCopy; } //++ ------------------------------------------------------------------------------------ -// Details: Determine if *this object is a derived from CDataObjectBase. -// Type: Overridden. -// Args: T - The object's type. -// Return: bool - True = *this is derived from CDataObjectBase -// - False = *this is an instance of the base class. -// Throws: None. +// Details: Determine if *this object is a derived from CDataObjectBase. +// Type: Overridden. +// Args: T - The object's type. +// Return: bool - True = *this is derived from CDataObjectBase +// - False = *this is an instance of the base class. +// Throws: None. //-- -template< typename T > -bool CMIUtilVariant::CDataObject< T >::GetIsDerivedClass( void ) const +template +bool +CMIUtilVariant::CDataObject::GetIsDerivedClass(void) const { - return true; + return true; } //++ ------------------------------------------------------------------------------------ -// Details: Perform a bitwise copy of *this object. -// Type: Overridden. -// Args: T - The object's type. -// vrOther - (R) The other object. -// Return: None. -// Throws: None. +// Details: Perform a bitwise copy of *this object. +// Type: Overrideable. +// Args: T - The object's type. +// vrOther - (R) The other object. +// Return: None. +// Throws: None. //-- -template< typename T > -void CMIUtilVariant::CDataObject< T >::Copy( const CDataObject & vrOther ) +template +void +CMIUtilVariant::CDataObject::Duplicate(const CDataObject &vrOther) { - CDataObjectBase::Copy( vrOther ); - m_dataObj = vrOther.m_dataObj; + CDataObjectBase::Copy(vrOther); + m_dataObj = vrOther.m_dataObj; } //++ ------------------------------------------------------------------------------------ -// Details: Release any resources used by *this object. -// Type: Overridden. -// Args: None. -// Return: None. -// Throws: None. +// Details: Release any resources used by *this object. +// Type: Overridden. +// Args: None. +// Return: None. +// Throws: None. //-- -template< typename T > -void CMIUtilVariant::CDataObject< T >::Destroy( void ) +template +void +CMIUtilVariant::CDataObject::Destroy(void) { - CDataObjectBase::Destroy(); + CDataObjectBase::Destroy(); } //--------------------------------------------------------------------------------------- @@ -253,36 +255,37 @@ void CMIUtilVariant::CDataObject< T >::Destroy( void ) //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ -// Details: Assign to the variant an object of a specified type. -// Type: Template method. -// Args: T - The object's type. -// vArg - (R) The object to store. -// Return: None. -// Throws: None. +// Details: Assign to the variant an object of a specified type. +// Type: Template method. +// Args: T - The object's type. +// vArg - (R) The object to store. +// Return: None. +// Throws: None. //-- -template< typename T > -void CMIUtilVariant::Set( const T & vArg ) +template +void +CMIUtilVariant::Set(const T &vArg) { - m_pDataObject = new CDataObject< T >( vArg ); + m_pDataObject = new CDataObject(vArg); } //++ ------------------------------------------------------------------------------------ -// Details: Retrieve the data object from *this variant. -// Type: Template method. -// Args: T - The object's type. -// Return: T * - Pointer the data object, NULL = data object not assigned to *this variant. -// Throws: None. +// Details: Retrieve the data object from *this variant. +// Type: Template method. +// Args: T - The object's type. +// Return: T * - Pointer the data object, NULL = data object not assigned to *this variant. +// Throws: None. //-- -template< typename T > -T * CMIUtilVariant::Get( void ) const +template +T * +CMIUtilVariant::Get(void) const { - if( (m_pDataObject != nullptr) && m_pDataObject->GetIsDerivedClass() ) - { - CDataObject< T > * pDataObj = static_cast< CDataObject< T > * >( m_pDataObject ); - return &pDataObj->GetDataObject(); - } + if ((m_pDataObject != nullptr) && m_pDataObject->GetIsDerivedClass()) + { + CDataObject *pDataObj = static_cast *>(m_pDataObject); + return &pDataObj->GetDataObject(); + } - // Do not use a CDataObjectBase object, use only CDataObjectBase derived objects - return nullptr; + // Do not use a CDataObjectBase object, use only CDataObjectBase derived objects + return nullptr; } - diff --git a/tools/lldb-mi/Platform.cpp b/tools/lldb-mi/Platform.cpp index c0208b3518c0..6ff998d2265f 100644 --- a/tools/lldb-mi/Platform.cpp +++ b/tools/lldb-mi/Platform.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // this file is only relevant for Visual C++ -#if defined( _MSC_VER ) +#if defined(_MSC_VER) #include #include @@ -19,89 +19,88 @@ static sighandler_t _ctrlHandler = NULL; // the default console control handler -BOOL -WINAPI CtrlHandler (DWORD ctrlType) +BOOL WINAPI CtrlHandler(DWORD ctrlType) { - if ( _ctrlHandler != NULL ) + if (_ctrlHandler != NULL) { - _ctrlHandler( 0 ); + _ctrlHandler(0); return TRUE; } return FALSE; } int -ioctl (int d, int request, ...) +ioctl(int d, int request, ...) { - switch ( request ) + switch (request) { - // request the console windows size - case ( TIOCGWINSZ ): + // request the console windows size + case (TIOCGWINSZ): { va_list vl; - va_start(vl,request); - // locate the window size structure on stack - winsize *ws = va_arg(vl, winsize*); + va_start(vl, request); + // locate the window size structure on stack + winsize *ws = va_arg(vl, winsize *); // get screen buffer information CONSOLE_SCREEN_BUFFER_INFO info; - if ( GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &info ) == TRUE ) + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info) == TRUE) // fill in the columns ws->ws_col = info.dwMaximumWindowSize.X; va_end(vl); return 0; } break; - default: - assert( !"Not implemented!" ); + default: + assert(!"Not implemented!"); } return -1; } int -kill (pid_t pid, int sig) +kill(pid_t pid, int sig) { // is the app trying to kill itself - if ( pid == getpid( ) ) - exit( sig ); + if (pid == getpid()) + exit(sig); // - assert( !"Not implemented!" ); + assert(!"Not implemented!"); return -1; } int -tcsetattr (int fd, int optional_actions, const struct termios *termios_p) +tcsetattr(int fd, int optional_actions, const struct termios *termios_p) { - assert( !"Not implemented!" ); + assert(!"Not implemented!"); return -1; } int -tcgetattr (int fildes, struct termios *termios_p) +tcgetattr(int fildes, struct termios *termios_p) { -// assert( !"Not implemented!" ); + // assert( !"Not implemented!" ); // error return value (0=success) return -1; } sighandler_t -signal (int sig, sighandler_t sigFunc) +signal(int sig, sighandler_t sigFunc) { - switch ( sig ) + switch (sig) { - case ( SIGINT ): + case (SIGINT): { _ctrlHandler = sigFunc; - SetConsoleCtrlHandler( CtrlHandler, TRUE ); + SetConsoleCtrlHandler(CtrlHandler, TRUE); } break; - case ( SIGPIPE ): - case ( SIGWINCH ): - case ( SIGTSTP ): - case ( SIGCONT ): - // ignore these for now - break; - default: - assert( !"Not implemented!" ); + case (SIGPIPE): + case (SIGWINCH): + case (SIGTSTP): + case (SIGCONT): + // ignore these for now + break; + default: + assert(!"Not implemented!"); } return 0; } diff --git a/tools/lldb-mi/Platform.h b/tools/lldb-mi/Platform.h index 443eedcef1ee..7c351310b255 100644 --- a/tools/lldb-mi/Platform.h +++ b/tools/lldb-mi/Platform.h @@ -8,102 +8,102 @@ //===----------------------------------------------------------------------===// #pragma once -#if defined( _MSC_VER ) - - // this will stop signal.h being included - #define _INC_SIGNAL - - #include - #include - #include - #include - #include - - // This is not used by MI - struct timeval - { - long tv_sec; - long tv_usec; - }; - - struct winsize - { - long ws_col; - }; - - typedef unsigned char cc_t; - typedef unsigned int speed_t; - typedef unsigned int tcflag_t; - - // fcntl.h // This is not used by MI - #define O_NOCTTY 0400 - - // ioctls.h - #define TIOCGWINSZ 0x5413 - - // tcsetattr arguments - #define TCSANOW 0 - - #define NCCS 32 - struct termios - { - tcflag_t c_iflag; // input mode flags - tcflag_t c_oflag; // output mode flags - tcflag_t c_cflag; // control mode flags - tcflag_t c_lflag; // local mode flags - cc_t c_line; // line discipline - cc_t c_cc[NCCS]; // control characters - speed_t c_ispeed; // input speed - speed_t c_ospeed; // output speed - }; - - typedef long pid_t; - - #define STDIN_FILENO 0 - #define PATH_MAX MAX_PATH - #define snprintf _snprintf - - extern int ioctl( int d, int request, ... ); - extern int kill ( pid_t pid, int sig ); - extern int tcsetattr( int fd, int optional_actions, const struct termios *termios_p ); - extern int tcgetattr( int fildes, struct termios *termios_p ); - - // signal handler function pointer type - typedef void (*sighandler_t)(int); - - // CODETAG_IOR_SIGNALS - // signal.h - #define SIGINT 2 // Terminal interrupt signal - #define SIGQUIT 3 // Terminal quit signal - #define SIGKILL 9 // Kill (cannot be caught or ignored) - #define SIGPIPE 13 // Write on a pipe with no one to read it - #define SIGCONT 18 // Continue executing, if stopped. - #define SIGTSTP 20 // Terminal stop signal - #define SIGSTOP 23 // Stop executing (cannot be caught or ignored) - #define SIGWINCH 28 // (== SIGVTALRM) - #define SIG_DFL ( (sighandler_t) -1 ) // Default handler - #define SIG_IGN ( (sighandler_t) -2 ) // Ignored - - extern sighandler_t signal( int sig, sighandler_t ); +#if defined(_MSC_VER) + +// this will stop signal.h being included +#define _INC_SIGNAL + +#include +#include +#include +#include +#include + +// This is not used by MI +struct timeval +{ + long tv_sec; + long tv_usec; +}; + +struct winsize +{ + long ws_col; +}; + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +// fcntl.h // This is not used by MI +#define O_NOCTTY 0400 + +// ioctls.h +#define TIOCGWINSZ 0x5413 + +// tcsetattr arguments +#define TCSANOW 0 + +#define NCCS 32 +struct termios +{ + tcflag_t c_iflag; // input mode flags + tcflag_t c_oflag; // output mode flags + tcflag_t c_cflag; // control mode flags + tcflag_t c_lflag; // local mode flags + cc_t c_line; // line discipline + cc_t c_cc[NCCS]; // control characters + speed_t c_ispeed; // input speed + speed_t c_ospeed; // output speed +}; + +typedef long pid_t; + +#define STDIN_FILENO 0 +#define PATH_MAX MAX_PATH +#define snprintf _snprintf + +extern int ioctl(int d, int request, ...); +extern int kill(pid_t pid, int sig); +extern int tcsetattr(int fd, int optional_actions, const struct termios *termios_p); +extern int tcgetattr(int fildes, struct termios *termios_p); + +// signal handler function pointer type +typedef void (*sighandler_t)(int); + +// CODETAG_IOR_SIGNALS +// signal.h +#define SIGINT 2 // Terminal interrupt signal +#define SIGQUIT 3 // Terminal quit signal +#define SIGKILL 9 // Kill (cannot be caught or ignored) +#define SIGPIPE 13 // Write on a pipe with no one to read it +#define SIGCONT 18 // Continue executing, if stopped. +#define SIGTSTP 20 // Terminal stop signal +#define SIGSTOP 23 // Stop executing (cannot be caught or ignored) +#define SIGWINCH 28 // (== SIGVTALRM) +#define SIG_DFL ((sighandler_t)-1) // Default handler +#define SIG_IGN ((sighandler_t)-2) // Ignored + +extern sighandler_t signal(int sig, sighandler_t); #else - #include +#include - #include - #include - #include - #include - #include +#include +#include +#include +#include +#include - #include - #include - #include +#include +#include +#include - #if defined(__FreeBSD__) - #include - #else - #include - #endif +#if defined(__FreeBSD__) +#include +#else +#include +#endif #endif diff --git a/tools/lldb-platform/lldb-platform.cpp b/tools/lldb-platform/lldb-platform.cpp index 0ab292aa4afb..f1c1a982850a 100644 --- a/tools/lldb-platform/lldb-platform.cpp +++ b/tools/lldb-platform/lldb-platform.cpp @@ -25,10 +25,10 @@ // Other libraries and framework includes #include "lldb/lldb-private-log.h" #include "lldb/Core/Error.h" -#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/ConnectionMachPort.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/HostGetOpt.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -233,10 +233,6 @@ main (int argc, char *argv[]) exit(option_error); } - // Skip any options we consumed with getopt_long_only - argc -= optind; - argv += optind; - // Execute any LLDB commands that we were asked to evaluate. for (const auto &lldb_command : lldb_commands) { -- cgit v1.2.3